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

Add pre-commit hook for bsrefmt. Run refmt over codebase. (#15)

+930 -794
__tests__/wonka_test.re
···
it("sends list items to a puller sink", () => {
let source = Wonka.fromList([10, 20, 30]);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
-
source((.signal) => {
switch (signal) {
-
| Start(x) => talkback := x;
-
| Push(_) => ignore(Js.Array.push(signal, signals));
| End => ignore(Js.Array.push(signal, signals))
-
};
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(signals) == [| Push(10), Push(20), Push(30), End |];
});
});
···
open! Expect.Operators;
it("sends array items to a puller sink", () => {
-
let source = Wonka.fromArray([| 10, 20, 30 |]);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = ref([||]);
-
source((.signal) => {
switch (signal) {
-
| Start(x) => {
talkback := x;
-
x(.Pull);
-
}
-
| Push(_) => {
signals := Array.append(signals^, [|signal|]);
-
talkback^(.Pull);
}
-
| End => signals := Array.append(signals^, [|signal|]);
-
};
-
});
-
expect(signals^) == [| Push(10), Push(20), Push(30), End |];
});
it("does not blow up the stack when iterating something huge", () => {
let arr = Array.make(100000, 123);
let source = Wonka.fromArray(arr);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let values = [||];
-
source((.signal) => {
switch (signal) {
-
| Start(x) => {
talkback := x;
-
x(.Pull);
-
}
-
| Push(x) => {
ignore(Js.Array.push(x, values));
-
talkback^(.Pull);
}
-
| End => ()
-
};
-
});
expect(Array.length(values)) == Array.length(arr);
});
···
it("sends a single item to a puller sink", () => {
let source = Wonka.fromValue(123);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
-
source((.signal) => {
switch (signal) {
-
| Start(x) => talkback := x;
-
| Push(_) => ignore(Js.Array.push(signal, signals));
| End => ignore(Js.Array.push(signal, signals))
-
};
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull); /* one extra to check whether no signal comes back after it has ended */
-
expect(signals) == [| Push(123), End |];
});
});
···
open! Expect.Operators;
it("ends immediately", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
-
Wonka.empty((.signal) => {
switch (signal) {
-
| Start(x) => talkback := x;
| _ => ignore(Js.Array.push(signal, signals))
-
};
-
});
let _signals = Array.copy(signals);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect((_signals, signals)) == ([| End |], [| End |]);
});
});
···
open! Expect.Operators;
it("does not end", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let ended = ref(false);
-
Wonka.never((.signal) => {
switch (signal) {
-
| Start(x) => talkback := x;
| End => ended := true
| _ => ()
-
};
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
expect(ended^) === false;
});
···
it("maps all emissions of a source", () => {
let num = ref(1);
let nums = [||];
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
-
Wonka.map((._) => {
-
let res = num^;
-
num := num^ + 1;
-
res
-
}, sink => {
-
sink(.Start((.signal) => {
switch (signal) {
-
| Pull => sink(.Push(1));
| _ => ()
-
}
-
}));
-
}, (.signal) => {
-
switch (signal) {
-
| Start(x) => {
-
talkback := x;
-
x(.Pull);
-
}
-
| Push(x) when num^ < 6 => {
-
ignore(Js.Array.push(x, nums));
-
talkback^(.Pull);
-
}
-
| _ => ()
-
}
-
});
-
expect(nums) |> toEqual([|1, 2, 3, 4|])
});
-
testPromise("follows the spec for listenables", () => {
-
Wonka_thelpers.testWithListenable(Wonka.map((.x) => x))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testTalkbackEnd(Wonka.map((.x) => x))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
it("filters emissions according to a predicate", () => {
let i = ref(1);
let nums = [||];
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
-
Wonka.filter((.x) => x mod 2 === 0, sink => {
-
sink(.Start((.signal) => {
switch (signal) {
-
| Pull => {
-
let num = i^;
-
i := i^ + 1;
-
sink(.Push(num));
-
}
| _ => ()
-
}
-
}));
-
}, (.signal) => {
-
switch (signal) {
-
| Start(x) => {
-
talkback := x;
-
x(.Pull);
-
}
-
| Push(x) when x < 6 => {
-
ignore(Js.Array.push(x, nums));
-
talkback^(.Pull);
-
}
-
| _ => ()
-
}
-
});
-
expect(nums) |> toEqual([|2, 4|])
});
-
testPromise("follows the spec for listenables", () => {
-
Wonka_thelpers.testWithListenable(Wonka.filter((._) => true))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("follows the spec for listenables when filtering", () => {
-
Wonka_thelpers.testWithListenable(Wonka.filter((._) => false))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull |], [| End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testTalkbackEnd(Wonka.filter((._) => true))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("folds emissions using an initial seed value", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.scan((.acc, x) => acc + x, 0, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (i <= 3) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(3), Push(6), End |]);
});
-
testPromise("follows the spec for listenables", () => {
-
Wonka_thelpers.testWithListenable(Wonka.scan((._, x) => x, 0))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testTalkbackEnd(Wonka.scan((._, x) => x, 0))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
it("merges different sources into a single one", () => {
let a = Wonka.fromList([1, 2, 3]);
let b = Wonka.fromList([4, 5, 6]);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
-
let source = Wonka.merge([| a, b |]);
-
source((.signal) => {
switch (signal) {
-
| Start(x) => {
talkback := x;
-
x(.Pull);
-
}
-
| Push(_) => {
ignore(Js.Array.push(signal, signals));
-
talkback^(.Pull);
}
-
| End => ignore(Js.Array.push(signal, signals))
-
};
-
});
-
expect(signals) == [| Push(1), Push(2), Push(3), Push(4), Push(5), Push(6), End |];
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(source => Wonka.merge([|source|]))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Pull |], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
Wonka_thelpers.testTalkbackEnd(source => Wonka.merge([|source|]))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Close |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
-
});
});
describe("concat", () => {
···
it("concatenates different sources into a single one", () => {
let a = Wonka.fromList([1, 2, 3]);
let b = Wonka.fromList([4, 5, 6]);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
-
let source = Wonka.concat([| a, b |]);
-
source((.signal) => {
switch (signal) {
-
| Start(x) => {
talkback := x;
-
x(.Pull);
-
}
-
| Push(_) => {
ignore(Js.Array.push(signal, signals));
-
talkback^(.Pull);
}
-
| End => ignore(Js.Array.push(signal, signals))
-
};
-
});
-
expect(signals) == [| Push(1), Push(2), Push(3), Push(4), Push(5), Push(6), End |];
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(source => Wonka.concat([|source|]))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Pull |], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
Wonka_thelpers.testTalkbackEnd(source => Wonka.concat([|source|]))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Close |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
-
});
});
describe("share", () => {
open Expect;
it("shares an underlying source with all sinks", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
-
let aborterTb = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
let nums = [||];
-
let source = Wonka.share(sink => {
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (i <= 2) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
}));
-
});
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, nums))
}
-
});
-
source((.signal) => {
switch (signal) {
| Start(_) => ()
| _ => ignore(Js.Array.push(signal, nums))
}
-
});
-
source((.signal) => {
switch (signal) {
| Start(tb) => aborterTb := tb
-
| _ => {
ignore(Js.Array.push(signal, nums));
-
aborterTb^(.Close);
}
-
}
-
});
-
talkback^(.Pull);
let numsA = Array.copy(nums);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect((numsA, nums)) |> toEqual(([| Push(1), Push(1), Push(1) |], [| Push(1), Push(1), Push(1), Push(2), Push(2), End, End |]));
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.share)
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.share)
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("combines the latest values of two sources", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let makeSource = (factor: int) => {
let num = ref(1);
sink => {
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
if (num^ <= 2) {
-
let i = num^ * factor;
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
}));
-
}
};
let sourceA = makeSource(1);
···
let source = Wonka.combine(sourceA, sourceB);
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push((1, 2)), Push((2, 2)), Push((2, 4)), End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(source => {
let shared = Wonka.share(source);
-
Wonka.combine(shared, shared)
})
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push((1, 1)), Push((2, 1)), Push((2, 2)), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(source => {
let shared = Wonka.share(source);
-
Wonka.combine(shared, shared)
})
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push((1, 1)) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("only lets a maximum number of values through", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.take(2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(2), End |]);
});
-
it("accepts the end of the source when max number of emissions is not reached", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.take(2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (i < 2) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.take(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testWithListenable(Wonka.take(1))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1), End |]))
-
|> Js.Promise.resolve
-
})
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.take(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("only lets the last n values through on an entirely new source", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.takeLast(2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when num^ <= 4 => {
-
let i = num^;
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| Pull => sink(.End)
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(3), Push(4), End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.takeLast(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Pull |], [| /* empty since the source is a pullable */ |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
Wonka_thelpers.testTalkbackEnd(Wonka.takeLast(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull |], [| |]))
-
|> Js.Promise.resolve
-
})
-
});
});
describe("takeWhile", () => {
open Expect;
it("only lets the last n values through on an entirely new source", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.takeWhile((.x) => x <= 2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(2), End |]);
});
-
it("accepts the end of the source when max number of emissions is not reached", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.takeWhile((.x) => x <= 5, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (i < 2) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), End |]);
});
-
testPromise("follows the spec for listenables", () => {
-
Wonka_thelpers.testWithListenable(Wonka.takeWhile((._) => true))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testWithListenable(Wonka.takeWhile((._) => false))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| End |]))
-
|> Js.Promise.resolve
-
})
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testTalkbackEnd(Wonka.takeWhile((._) => true))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("only lets the last n values through on an entirely new source", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let notify = ref((_: Wonka_types.talkbackT) => ());
let num = ref(1);
let notifier = sink => {
-
notify := signal => switch (signal) {
-
| Pull => sink(.Push(0));
-
| _ => ()
-
};
-
sink(.Start(Wonka_helpers.talkbackPlaceholder));
};
-
let source = Wonka.takeUntil(notifier, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when num^ <= 4 => {
-
let i = num^;
-
if (i === 3) notify^(Pull);
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(2), End |]);
});
-
it("accepts the end of the source when max number of emissions is not reached", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let notifier = sink => sink(.Start(Wonka_helpers.talkbackPlaceholder));
-
let source = Wonka.takeUntil(notifier, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (num^ <= 2) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(2), End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.takeUntil(Wonka.never))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testWithListenable(Wonka.takeUntil(Wonka.fromValue(0)))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| End |]))
-
|> Js.Promise.resolve
-
})
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.takeUntil(Wonka.never))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
describe("skip", () => {
open Expect;
-
it("only lets values through after a number of values have been filtered out", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let source = Wonka.skip(2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when num^ <= 4 => {
-
let i = num^;
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| Pull => sink(.End)
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(3), Push(4), End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.skip(0))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("follows the spec for listenables when skipping the source", () => {
Wonka_thelpers.testWithListenable(Wonka.skip(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull |], [| End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.skip(10))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, end_ |], [| |]))
-
|> Js.Promise.resolve
-
})
});
});
describe("skipWhile", () => {
open Expect;
-
it("only lets values through after the predicate returned false, including the first such value", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
-
let num = ref(1);
-
let source = Wonka.skipWhile((.x) => x <= 2, sink => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when num^ <= 4 => {
-
let i = num^;
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| Pull => sink(.End)
-
| _ => ()
-
}
-
})));
-
let res = [||];
-
source((.signal) => {
-
switch (signal) {
-
| Start(x) => talkback := x
-
| _ => ignore(Js.Array.push(signal, res))
-
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(3), Push(4), End |]);
-
});
-
testPromise("follows the spec for listenables", () => {
-
Wonka_thelpers.testWithListenable(Wonka.skipWhile((._) => false))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([||], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("follows the spec for listenables when skipping the source", () => {
-
Wonka_thelpers.testWithListenable(Wonka.skipWhile((._) => true))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull |], [| End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
-
Wonka_thelpers.testTalkbackEnd(Wonka.skipWhile((._) => false))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
···
open Expect;
it("only lets values through after the notifier emits a value", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let notify = ref((_: Wonka_types.talkbackT) => ());
let num = ref(1);
let notifier = sink => {
-
notify := signal => switch (signal) {
-
| Pull => sink(.Push(0));
-
| _ => ()
-
};
-
sink(.Start(Wonka_helpers.talkbackPlaceholder));
};
-
let source = Wonka.skipUntil(notifier, (sink) => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when num^ <= 4 => {
-
let i = num^;
-
if (i === 3) notify^(Pull);
-
num := num^ + 1;
-
sink(.Push(i));
-
}
-
| Pull => sink(.End)
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(3), Push(4), End |]);
});
-
it("accepts the end of the source when max number of emissions is not reached", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let num = ref(1);
-
let notifier = sink => sink(.Start(Wonka_helpers.talkbackPlaceholder));
-
let source = Wonka.skipUntil(notifier, (sink) => sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
let i = num^;
-
if (i < 2) {
-
num := num^ + 1;
-
sink(.Push(i));
-
} else {
-
sink(.End);
-
}
-
}
-
| _ => ()
-
}
-
})));
let res = [||];
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| End |]);
});
-
testPromise("follows the spec for listenables", () => {
Wonka_thelpers.testWithListenable(Wonka.skipUntil(Wonka.never))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, Pull, Pull |], [| End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("follows the spec for listenables when skipping the source", () => {
Wonka_thelpers.testWithListenable(Wonka.skipUntil(Wonka.fromValue(0)))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull |], [| Push(1), Push(2), End |]))
-
|> Js.Promise.resolve
-
})
-
});
-
testPromise("ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.skipUntil(Wonka.fromValue(0)))
-
|> Js.Promise.then_(x => {
-
expect(x)
-
|> toEqual(([| Pull, end_ |], [| Push(1) |]))
-
|> Js.Promise.resolve
-
})
});
});
-
describe("flatten", () => {
-
open Expect;
-
it("merges the result of multiple pullables into its source", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
-
let source = Wonka.fromList([ Wonka.fromList([ 1, 2 ]), Wonka.fromList([ 1, 2 ]) ])
-
|> Wonka.flatten;
-
let res = [||];
-
source((.signal) => {
-
switch (signal) {
-
| Start(x) => talkback := x
-
| _ => ignore(Js.Array.push(signal, res))
-
}
-
});
-
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
talkback^(.Pull);
-
expect(res) |> toEqual([| Push(1), Push(2), Push(1), Push(2), End |]);
-
});
-
});
describe("switchMap", () => {
afterEach(() => Jest.useRealTimers());
-
open Expect;
open! Expect.Operators;
···
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
-
let source = Wonka.switchMap((.x) => Wonka.fromList([x * x]), a);
-
source((.signal) =>
switch (signal) {
| Start(x) =>
talkback := x;
-
x(.Pull);
| Push(_) =>
ignore(Js.Array.push(signal, signals));
-
talkback^(.Pull);
| End => ignore(Js.Array.push(signal, signals))
}
);
···
let a = Wonka.interval(100);
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signals = [||];
let source =
-
Wonka.switchMap((._) => Wonka.interval(25), a) |> Wonka.take(5);
-
source((.signal) =>
switch (signal) {
| Start(x) =>
talkback := x;
-
x(.Pull);
| Push(_) =>
ignore(Js.Array.push(signal, signals));
-
talkback^(.Pull);
| End => ignore(Js.Array.push(signal, signals))
}
);
···
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(source =>
-
Wonka.switchMap((.x) => x, Wonka.fromList([source]))
)
|> Js.Promise.then_(x =>
expect(x)
···
testPromise(
"ends itself and source when its talkback receives the End signal", () =>
Wonka_thelpers.testTalkbackEnd(source =>
-
Wonka.switchMap((.x) => x, Wonka.fromList([source]))
)
|> Js.Promise.then_(x =>
expect(x)
···
});
describe("sink factories", () => {
-
describe("forEach", () => {
-
open Expect;
-
it("calls a function for each emission of the passed source", () => {
-
let i = ref(0);
-
let nums = [||];
-
let source = sink => {
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when i^ < 4 => {
-
let num = i^;
-
i := i^ + 1;
-
sink(.Push(num));
-
}
-
| Pull => sink(.End)
-
| _ => ()
-
}
-
}));
-
};
-
Wonka.forEach((.x) => ignore(Js.Array.push(x, nums)), source);
-
expect(nums) |> toEqual([| 0, 1, 2, 3 |])
-
});
-
});
-
describe("subscribe", () => {
-
open Expect;
-
it("calls a function for each emission of the passed source and stops when unsubscribed", () => {
-
let i = ref(0);
-
let nums = [||];
-
let push = ref(() => ());
-
-
let source = sink => {
-
push := () => {
-
let num = i^;
-
i := i^ + 1;
-
sink(.Push(num));
-
};
-
sink(.Start(Wonka_helpers.talkbackPlaceholder));
-
};
-
let { unsubscribe } = Wonka.subscribe((.x) => ignore(Js.Array.push(x, nums)), source);
-
push^();
-
push^();
-
unsubscribe();
-
push^();
-
push^();
-
-
expect(nums) |> toEqual([| 0, 1 |])
-
});
-
});
});
-
describe("chains (integration)", () => {
-
open Expect;
-
it("fromArray, map, forEach", () => {
-
let input = Array.mapi((i, _) => i, Array.make(1000, 1));
-
let output = Array.map(x => string_of_int(x));
-
let actual = [||];
-
-
input
|> Wonka.fromArray
-
|> Wonka.map((.x) => string_of_int(x))
-
|> Wonka.forEach((.x) => ignore(Js.Array.push(x, actual)));
-
expect(output) |> toEqual(output)
-
});
-
});
describe("subject", () => {
open Expect;
···
let subject = Wonka.makeSubject();
-
subject.source((.signal) =>
switch (signal) {
| Start(_) => ignore()
| Push(_) => ignore(Js.Array.push(signal, signals))
···
});
it("handles multiple sinks", () => {
-
let talkback = ref((._: Wonka_types.talkbackT) => ());
let signalsOne = [||];
let signalsTwo = [||];
let subject = Wonka.makeSubject();
-
subject.source((.signal) =>
switch (signal) {
| Start(x) => talkback := x
| Push(_) => ignore(Js.Array.push(signal, signalsOne))
···
}
);
-
subject.source((.signal) =>
switch (signal) {
| Start(_) => ignore()
| Push(_) => ignore(Js.Array.push(signal, signalsTwo))
···
subject.next(20);
subject.next(30);
-
talkback^(.Close);
subject.next(40);
subject.next(50);
···
});
it("handles multiple sinks that subscribe and close at different times", () => {
-
let talkbackOne = ref((._: Wonka_types.talkbackT) => ());
-
let talkbackTwo = ref((._: Wonka_types.talkbackT) => ());
let signalsOne = [||];
let signalsTwo = [||];
···
subject.next(10);
subject.next(20);
-
subject.source((.signal) =>
switch (signal) {
| Start(x) => talkbackOne := x
| Push(_) => ignore(Js.Array.push(signal, signalsOne))
···
subject.next(30);
-
subject.source((.signal) =>
switch (signal) {
| Start(x) => talkbackTwo := x
| Push(_) => ignore(Js.Array.push(signal, signalsTwo))
···
subject.next(40);
subject.next(50);
-
talkbackTwo^(.Close);
subject.next(60);
-
talkbackOne^(.Close);
subject.next(70);
subject.complete();
···
it("sends list items to a puller sink", () => {
let source = Wonka.fromList([10, 20, 30]);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
source((. signal) =>
switch (signal) {
+
| Start(x) => talkback := x
+
| Push(_) => ignore(Js.Array.push(signal, signals))
| End => ignore(Js.Array.push(signal, signals))
+
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(signals) == [|Push(10), Push(20), Push(30), End|];
});
});
···
open! Expect.Operators;
it("sends array items to a puller sink", () => {
+
let source = Wonka.fromArray([|10, 20, 30|]);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = ref([||]);
+
source((. signal) =>
switch (signal) {
+
| Start(x) =>
talkback := x;
+
x(. Pull);
+
| Push(_) =>
signals := Array.append(signals^, [|signal|]);
+
talkback^(. Pull);
+
| End => signals := Array.append(signals^, [|signal|])
}
+
);
+
expect(signals^) == [|Push(10), Push(20), Push(30), End|];
});
it("does not blow up the stack when iterating something huge", () => {
let arr = Array.make(100000, 123);
let source = Wonka.fromArray(arr);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let values = [||];
+
source((. signal) =>
switch (signal) {
+
| Start(x) =>
talkback := x;
+
x(. Pull);
+
| Push(x) =>
ignore(Js.Array.push(x, values));
+
talkback^(. Pull);
+
| End => ()
}
+
);
expect(Array.length(values)) == Array.length(arr);
});
···
it("sends a single item to a puller sink", () => {
let source = Wonka.fromValue(123);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
source((. signal) =>
switch (signal) {
+
| Start(x) => talkback := x
+
| Push(_) => ignore(Js.Array.push(signal, signals))
| End => ignore(Js.Array.push(signal, signals))
+
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull); /* one extra to check whether no signal comes back after it has ended */
+
expect(signals) == [|Push(123), End|];
});
});
···
open! Expect.Operators;
it("ends immediately", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
Wonka.empty((. signal) =>
switch (signal) {
+
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, signals))
+
}
+
);
let _signals = Array.copy(signals);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect((_signals, signals)) == ([|End|], [|End|]);
});
});
···
open! Expect.Operators;
it("does not end", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let ended = ref(false);
+
Wonka.never((. signal) =>
switch (signal) {
+
| Start(x) => talkback := x
| End => ended := true
| _ => ()
+
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
expect(ended^) === false;
});
···
it("maps all emissions of a source", () => {
let num = ref(1);
let nums = [||];
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
+
Wonka.map(
+
(. _) => {
+
let res = num^;
+
num := num^ + 1;
+
res;
+
},
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull => sink(. Push(1))
+
| _ => ()
+
},
+
),
+
),
+
(. signal) =>
switch (signal) {
+
| Start(x) =>
+
talkback := x;
+
x(. Pull);
+
| Push(x) when num^ < 6 =>
+
ignore(Js.Array.push(x, nums));
+
talkback^(. Pull);
| _ => ()
+
},
+
);
+
expect(nums) |> toEqual([|1, 2, 3, 4|]);
});
+
testPromise("follows the spec for listenables", () =>
+
Wonka_thelpers.testWithListenable(Wonka.map((. x) => x))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testTalkbackEnd(Wonka.map((. x) => x))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
it("filters emissions according to a predicate", () => {
let i = ref(1);
let nums = [||];
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
+
Wonka.filter(
+
(. x) => x mod 2 === 0,
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let num = i^;
+
i := i^ + 1;
+
sink(. Push(num));
+
| _ => ()
+
},
+
),
+
),
+
(. signal) =>
switch (signal) {
+
| Start(x) =>
+
talkback := x;
+
x(. Pull);
+
| Push(x) when x < 6 =>
+
ignore(Js.Array.push(x, nums));
+
talkback^(. Pull);
| _ => ()
+
},
+
);
+
expect(nums) |> toEqual([|2, 4|]);
});
+
testPromise("follows the spec for listenables", () =>
+
Wonka_thelpers.testWithListenable(Wonka.filter((. _) => true))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise("follows the spec for listenables when filtering", () =>
+
Wonka_thelpers.testWithListenable(Wonka.filter((. _) => false))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull|], [|End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testTalkbackEnd(Wonka.filter((. _) => true))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("folds emissions using an initial seed value", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.scan(
+
(. acc, x) => acc + x,
+
0,
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (i <= 3) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
),
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), Push(3), Push(6), End|]);
});
+
testPromise("follows the spec for listenables", () =>
+
Wonka_thelpers.testWithListenable(Wonka.scan((. _, x) => x, 0))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testTalkbackEnd(Wonka.scan((. _, x) => x, 0))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
it("merges different sources into a single one", () => {
let a = Wonka.fromList([1, 2, 3]);
let b = Wonka.fromList([4, 5, 6]);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
let source = Wonka.merge([|a, b|]);
+
source((. signal) =>
switch (signal) {
+
| Start(x) =>
talkback := x;
+
x(. Pull);
+
| Push(_) =>
ignore(Js.Array.push(signal, signals));
+
talkback^(. Pull);
+
| End => ignore(Js.Array.push(signal, signals))
}
+
);
+
expect(signals)
+
== [|Push(1), Push(2), Push(3), Push(4), Push(5), Push(6), End|];
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(source => Wonka.merge([|source|]))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull, Pull|], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () =>
Wonka_thelpers.testTalkbackEnd(source => Wonka.merge([|source|]))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull, Close|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
)
+
);
});
describe("concat", () => {
···
it("concatenates different sources into a single one", () => {
let a = Wonka.fromList([1, 2, 3]);
let b = Wonka.fromList([4, 5, 6]);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
let source = Wonka.concat([|a, b|]);
+
source((. signal) =>
switch (signal) {
+
| Start(x) =>
talkback := x;
+
x(. Pull);
+
| Push(_) =>
ignore(Js.Array.push(signal, signals));
+
talkback^(. Pull);
+
| End => ignore(Js.Array.push(signal, signals))
}
+
);
+
expect(signals)
+
== [|Push(1), Push(2), Push(3), Push(4), Push(5), Push(6), End|];
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(source => Wonka.concat([|source|]))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull, Pull|], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () =>
Wonka_thelpers.testTalkbackEnd(source => Wonka.concat([|source|]))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull, Close|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
)
+
);
});
describe("share", () => {
open Expect;
it("shares an underlying source with all sinks", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
+
let aborterTb = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
let nums = [||];
+
let source =
+
Wonka.share(sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (i <= 2) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
)
+
);
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, nums))
}
+
);
+
source((. signal) =>
switch (signal) {
| Start(_) => ()
| _ => ignore(Js.Array.push(signal, nums))
}
+
);
+
source((. signal) =>
switch (signal) {
| Start(tb) => aborterTb := tb
+
| _ =>
ignore(Js.Array.push(signal, nums));
+
aborterTb^(. Close);
}
+
);
+
talkback^(. Pull);
let numsA = Array.copy(nums);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect((numsA, nums))
+
|> toEqual((
+
[|Push(1), Push(1), Push(1)|],
+
[|Push(1), Push(1), Push(1), Push(2), Push(2), End, End|],
+
));
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.share)
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.share)
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("combines the latest values of two sources", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let makeSource = (factor: int) => {
let num = ref(1);
sink => {
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
if (num^ <= 2) {
+
let i = num^ * factor;
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
}
+
| _ => ()
+
},
+
),
+
);
+
};
};
let sourceA = makeSource(1);
···
let source = Wonka.combine(sourceA, sourceB);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res)
+
|> toEqual([|Push((1, 2)), Push((2, 2)), Push((2, 4)), End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(source => {
let shared = Wonka.share(source);
+
Wonka.combine(shared, shared);
})
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual((
+
[||],
+
[|Push((1, 1)), Push((2, 1)), Push((2, 2)), End|],
+
))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(source => {
let shared = Wonka.share(source);
+
Wonka.combine(shared, shared);
})
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push((1, 1))|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("only lets a maximum number of values through", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.take(2, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
num := num^ + 1;
+
sink(. Push(i));
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), Push(2), End|]);
});
+
it(
+
"accepts the end of the source when max number of emissions is not reached",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.take(2, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (i < 2) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.take(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testWithListenable(Wonka.take(1))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1), End|]))
+
|> Js.Promise.resolve
+
);
});
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.take(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("only lets the last n values through on an entirely new source", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.takeLast(2, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when num^ <= 4 =>
+
let i = num^;
+
num := num^ + 1;
+
sink(. Push(i));
+
| Pull => sink(. End)
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(3), Push(4), End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.takeLast(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual((
+
[|Pull, Pull, Pull|],
+
[|/* empty since the source is a pullable */|],
+
))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () =>
Wonka_thelpers.testTalkbackEnd(Wonka.takeLast(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull|], [||]))
+
|> Js.Promise.resolve
+
)
+
);
});
describe("takeWhile", () => {
open Expect;
it("only lets the last n values through on an entirely new source", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.takeWhile(
+
(. x) => x <= 2,
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
num := num^ + 1;
+
sink(. Push(i));
+
| _ => ()
+
},
+
),
+
),
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), Push(2), End|]);
});
+
it(
+
"accepts the end of the source when max number of emissions is not reached",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.takeWhile(
+
(. x) => x <= 5,
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (i < 2) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
),
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), End|]);
});
+
testPromise("follows the spec for listenables", () =>
+
Wonka_thelpers.testWithListenable(Wonka.takeWhile((. _) => true))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testWithListenable(Wonka.takeWhile((. _) => false))
+
|> Js.Promise.then_(x =>
+
expect(x) |> toEqual(([|end_|], [|End|])) |> Js.Promise.resolve
+
);
});
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testTalkbackEnd(Wonka.takeWhile((. _) => true))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("only lets the last n values through on an entirely new source", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let notify = ref((_: Wonka_types.talkbackT) => ());
let num = ref(1);
let notifier = sink => {
+
notify :=
+
(
+
signal =>
+
switch (signal) {
+
| Pull => sink(. Push(0))
+
| _ => ()
+
}
+
);
+
sink(. Start(Wonka_helpers.talkbackPlaceholder));
};
+
let source =
+
Wonka.takeUntil(notifier, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when num^ <= 4 =>
+
let i = num^;
+
if (i === 3) {
+
notify^(Pull);
+
};
+
num := num^ + 1;
+
sink(. Push(i));
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), Push(2), End|]);
});
+
it(
+
"accepts the end of the source when max number of emissions is not reached",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let notifier = sink =>
+
sink(. Start(Wonka_helpers.talkbackPlaceholder));
+
let source =
+
Wonka.takeUntil(notifier, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (num^ <= 2) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(1), Push(2), End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.takeUntil(Wonka.never))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
testPromise("follows the spec for listenables when ending the source", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testWithListenable(Wonka.takeUntil(Wonka.fromValue(0)))
+
|> Js.Promise.then_(x =>
+
expect(x) |> toEqual(([|end_|], [|End|])) |> Js.Promise.resolve
+
);
});
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.takeUntil(Wonka.never))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
describe("skip", () => {
open Expect;
+
it(
+
"only lets values through after a number of values have been filtered out",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let source =
+
Wonka.skip(2, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when num^ <= 4 =>
+
let i = num^;
+
num := num^ + 1;
+
sink(. Push(i));
+
| Pull => sink(. End)
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(3), Push(4), End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.skip(0))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"follows the spec for listenables when skipping the source", () =>
Wonka_thelpers.testWithListenable(Wonka.skip(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull|], [|End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.skip(10))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, end_|], [||]))
+
|> Js.Promise.resolve
+
);
});
});
describe("skipWhile", () => {
open Expect;
+
it(
+
"only lets values through after the predicate returned false, including the first such value",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
+
let num = ref(1);
+
let source =
+
Wonka.skipWhile(
+
(. x) => x <= 2,
+
sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when num^ <= 4 =>
+
let i = num^;
+
num := num^ + 1;
+
sink(. Push(i));
+
| Pull => sink(. End)
+
| _ => ()
+
},
+
),
+
),
+
);
+
let res = [||];
+
source((. signal) =>
+
switch (signal) {
+
| Start(x) => talkback := x
+
| _ => ignore(Js.Array.push(signal, res))
+
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(3), Push(4), End|]);
+
},
+
);
+
testPromise("follows the spec for listenables", () =>
+
Wonka_thelpers.testWithListenable(Wonka.skipWhile((. _) => false))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([||], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"follows the spec for listenables when skipping the source", () =>
+
Wonka_thelpers.testWithListenable(Wonka.skipWhile((. _) => true))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull|], [|End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
+
Wonka_thelpers.testTalkbackEnd(Wonka.skipWhile((. _) => false))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
···
open Expect;
it("only lets values through after the notifier emits a value", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let notify = ref((_: Wonka_types.talkbackT) => ());
let num = ref(1);
let notifier = sink => {
+
notify :=
+
(
+
signal =>
+
switch (signal) {
+
| Pull => sink(. Push(0))
+
| _ => ()
+
}
+
);
+
sink(. Start(Wonka_helpers.talkbackPlaceholder));
};
+
let source =
+
Wonka.skipUntil(notifier, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when num^ <= 4 =>
+
let i = num^;
+
if (i === 3) {
+
notify^(Pull);
+
};
+
num := num^ + 1;
+
sink(. Push(i));
+
| Pull => sink(. End)
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|Push(3), Push(4), End|]);
});
+
it(
+
"accepts the end of the source when max number of emissions is not reached",
+
() => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let num = ref(1);
+
let notifier = sink =>
+
sink(. Start(Wonka_helpers.talkbackPlaceholder));
+
let source =
+
Wonka.skipUntil(notifier, sink =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
let i = num^;
+
if (i < 2) {
+
num := num^ + 1;
+
sink(. Push(i));
+
} else {
+
sink(. End);
+
};
+
| _ => ()
+
},
+
),
+
)
+
);
let res = [||];
+
source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res) |> toEqual([|End|]);
});
+
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(Wonka.skipUntil(Wonka.never))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, Pull, Pull|], [|End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"follows the spec for listenables when skipping the source", () =>
Wonka_thelpers.testWithListenable(Wonka.skipUntil(Wonka.fromValue(0)))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull|], [|Push(1), Push(2), End|]))
+
|> Js.Promise.resolve
+
)
+
);
+
testPromise(
+
"ends itself and source when its talkback receives the End signal", () => {
let end_: talkbackT = Close;
Wonka_thelpers.testTalkbackEnd(Wonka.skipUntil(Wonka.fromValue(0)))
+
|> Js.Promise.then_(x =>
+
expect(x)
+
|> toEqual(([|Pull, end_|], [|Push(1)|]))
+
|> Js.Promise.resolve
+
);
});
});
+
describe("flatten", () =>
+
Expect.(
+
it("merges the result of multiple pullables into its source", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
+
let source =
+
Wonka.fromList([Wonka.fromList([1, 2]), Wonka.fromList([1, 2])])
+
|> Wonka.flatten;
+
let res = [||];
+
source((. signal) =>
+
switch (signal) {
+
| Start(x) => talkback := x
+
| _ => ignore(Js.Array.push(signal, res))
+
}
+
);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
talkback^(. Pull);
+
expect(res)
+
|> toEqual([|Push(1), Push(2), Push(1), Push(2), End|]);
+
})
+
)
+
);
describe("switchMap", () => {
afterEach(() => Jest.useRealTimers());
open Expect;
open! Expect.Operators;
···
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
+
let source = Wonka.switchMap((. x) => Wonka.fromList([x * x]), a);
+
source((. signal) =>
switch (signal) {
| Start(x) =>
talkback := x;
+
x(. Pull);
| Push(_) =>
ignore(Js.Array.push(signal, signals));
+
talkback^(. Pull);
| End => ignore(Js.Array.push(signal, signals))
}
);
···
let a = Wonka.interval(100);
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signals = [||];
let source =
+
Wonka.switchMap((. _) => Wonka.interval(25), a) |> Wonka.take(5);
+
source((. signal) =>
switch (signal) {
| Start(x) =>
talkback := x;
+
x(. Pull);
| Push(_) =>
ignore(Js.Array.push(signal, signals));
+
talkback^(. Pull);
| End => ignore(Js.Array.push(signal, signals))
}
);
···
testPromise("follows the spec for listenables", () =>
Wonka_thelpers.testWithListenable(source =>
+
Wonka.switchMap((. x) => x, Wonka.fromList([source]))
)
|> Js.Promise.then_(x =>
expect(x)
···
testPromise(
"ends itself and source when its talkback receives the End signal", () =>
Wonka_thelpers.testTalkbackEnd(source =>
+
Wonka.switchMap((. x) => x, Wonka.fromList([source]))
)
|> Js.Promise.then_(x =>
expect(x)
···
});
describe("sink factories", () => {
+
describe("forEach", () =>
+
Expect.(
+
it("calls a function for each emission of the passed source", () => {
+
let i = ref(0);
+
let nums = [||];
+
let source = sink => {
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when i^ < 4 =>
+
let num = i^;
+
i := i^ + 1;
+
sink(. Push(num));
+
| Pull => sink(. End)
+
| _ => ()
+
},
+
),
+
);
+
};
+
Wonka.forEach((. x) => ignore(Js.Array.push(x, nums)), source);
+
expect(nums) |> toEqual([|0, 1, 2, 3|]);
+
})
+
)
+
);
+
describe("subscribe", () =>
+
Expect.(
+
it(
+
"calls a function for each emission of the passed source and stops when unsubscribed",
+
() => {
+
let i = ref(0);
+
let nums = [||];
+
let push = ref(() => ());
+
let source = sink => {
+
push :=
+
(
+
() => {
+
let num = i^;
+
i := i^ + 1;
+
sink(. Push(num));
+
}
+
);
+
sink(. Start(Wonka_helpers.talkbackPlaceholder));
+
};
+
let {unsubscribe} =
+
Wonka.subscribe(
+
(. x) => ignore(Js.Array.push(x, nums)),
+
source,
+
);
+
push^();
+
push^();
+
unsubscribe();
+
push^();
+
push^();
+
expect(nums) |> toEqual([|0, 1|]);
+
},
+
)
+
)
+
);
});
+
describe("chains (integration)", () =>
+
Expect.(
+
it("fromArray, map, forEach", () => {
+
let input = Array.mapi((i, _) => i, Array.make(1000, 1));
+
let output = Array.map(x => string_of_int(x));
+
let actual = [||];
+
input
|> Wonka.fromArray
+
|> Wonka.map((. x) => string_of_int(x))
+
|> Wonka.forEach((. x) => ignore(Js.Array.push(x, actual)));
+
expect(output) |> toEqual(output);
+
})
+
)
+
);
describe("subject", () => {
open Expect;
···
let subject = Wonka.makeSubject();
+
subject.source((. signal) =>
switch (signal) {
| Start(_) => ignore()
| Push(_) => ignore(Js.Array.push(signal, signals))
···
});
it("handles multiple sinks", () => {
+
let talkback = ref((. _: Wonka_types.talkbackT) => ());
let signalsOne = [||];
let signalsTwo = [||];
let subject = Wonka.makeSubject();
+
subject.source((. signal) =>
switch (signal) {
| Start(x) => talkback := x
| Push(_) => ignore(Js.Array.push(signal, signalsOne))
···
}
);
+
subject.source((. signal) =>
switch (signal) {
| Start(_) => ignore()
| Push(_) => ignore(Js.Array.push(signal, signalsTwo))
···
subject.next(20);
subject.next(30);
+
talkback^(. Close);
subject.next(40);
subject.next(50);
···
});
it("handles multiple sinks that subscribe and close at different times", () => {
+
let talkbackOne = ref((. _: Wonka_types.talkbackT) => ());
+
let talkbackTwo = ref((. _: Wonka_types.talkbackT) => ());
let signalsOne = [||];
let signalsTwo = [||];
···
subject.next(10);
subject.next(20);
+
subject.source((. signal) =>
switch (signal) {
| Start(x) => talkbackOne := x
| Push(_) => ignore(Js.Array.push(signal, signalsOne))
···
subject.next(30);
+
subject.source((. signal) =>
switch (signal) {
| Start(x) => talkbackTwo := x
| Push(_) => ignore(Js.Array.push(signal, signalsTwo))
···
subject.next(40);
subject.next(50);
+
talkbackTwo^(. Close);
subject.next(60);
+
talkbackOne^(. Close);
subject.next(70);
subject.complete();
+42 -31
__tests__/wonka_thelpers.re
···
open Wonka_types;
let testWithListenable = operator => {
-
let sink = ref((._: signalT(int)) => ());
let signals = [||];
let source = x => {
sink := x;
-
x(.Start((.signal) => {
-
ignore(Js.Array.push(signal, signals))
-
}));
};
-
let talkback = ref((._: talkbackT) => ());
let res = [||];
-
operator(source)((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
Js.Promise.make((~resolve, ~reject as _) => {
-
sink^(.Push(1));
-
ignore(Js.Global.setTimeout(() => {
-
sink^(.Push(2));
-
ignore(Js.Global.setTimeout(() => {
-
sink^(.End);
-
ignore(Js.Global.setTimeout(() => {
-
resolve(.(signals, res));
-
}, 0));
-
}, 0));
-
}, 0));
-
})
};
let testTalkbackEnd = operator => {
-
let sink = ref((._: signalT(int)) => ());
let signals: array(talkbackT) = [||];
let source = x => {
-
x(.Start((.signal) => ignore(Js.Array.push(signal, signals))));
sink := x;
};
-
let talkback = ref((._: talkbackT) => ());
let res = [||];
-
operator(source)((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
-
});
Js.Promise.make((~resolve, ~reject as _) => {
-
sink^(.Push(1));
-
ignore(Js.Global.setTimeout(() => {
-
talkback^(.Close);
-
ignore(Js.Global.setTimeout(() => {
-
resolve(.(signals, res));
-
}, 0));
-
}, 0));
-
})
};
···
open Wonka_types;
let testWithListenable = operator => {
+
let sink = ref((. _: signalT(int)) => ());
let signals = [||];
let source = x => {
sink := x;
+
x(. Start((. signal) => ignore(Js.Array.push(signal, signals))));
};
+
let talkback = ref((. _: talkbackT) => ());
let res = [||];
+
operator(source, (. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
Js.Promise.make((~resolve, ~reject as _) => {
+
sink^(. Push(1));
+
ignore(
+
Js.Global.setTimeout(
+
() => {
+
sink^(. Push(2));
+
ignore(
+
Js.Global.setTimeout(
+
() => {
+
sink^(. End);
+
ignore(
+
Js.Global.setTimeout(() => resolve(. (signals, res)), 0),
+
);
+
},
+
0,
+
),
+
);
+
},
+
0,
+
),
+
);
+
});
};
let testTalkbackEnd = operator => {
+
let sink = ref((. _: signalT(int)) => ());
let signals: array(talkbackT) = [||];
let source = x => {
+
x(. Start((. signal) => ignore(Js.Array.push(signal, signals))));
sink := x;
};
+
let talkback = ref((. _: talkbackT) => ());
let res = [||];
+
operator(source, (. signal) =>
switch (signal) {
| Start(x) => talkback := x
| _ => ignore(Js.Array.push(signal, res))
}
+
);
Js.Promise.make((~resolve, ~reject as _) => {
+
sink^(. Push(1));
+
ignore(
+
Js.Global.setTimeout(
+
() => {
+
talkback^(. Close);
+
ignore(Js.Global.setTimeout(() => resolve(. (signals, res)), 0));
+
},
+
0,
+
),
+
);
+
});
};
+14
package.json
···
"terser:cjs": "terser --config-file .terser.config.json -o ./dist/wonka.js ./dist/wonka.js",
"terser": "run-p terser:es terser:cjs",
"prettier": "prettier --write ./dist/*.js",
"prebundle": "rimraf ./dist",
"bundle": "microbundle --external none --no-compress --no-sourcemap --format es,cjs",
"postbundle": "run-s terser prettier",
···
"bs-platform": "^4.0.17",
"bundlesize": "^0.17.0",
"coveralls": "^3.0.0",
"microbundle": "^0.9.0",
"npm-run-all": "^4.1.5",
"prettier": "^1.15.3",
"rimraf": "^2.6.3",
"terser": "^3.14.1"
},
"prettier": {
"printWidth": 100
···
"terser:cjs": "terser --config-file .terser.config.json -o ./dist/wonka.js ./dist/wonka.js",
"terser": "run-p terser:es terser:cjs",
"prettier": "prettier --write ./dist/*.js",
+
"refmt": "bsrefmt --in-place **/**/*.re",
"prebundle": "rimraf ./dist",
"bundle": "microbundle --external none --no-compress --no-sourcemap --format es,cjs",
"postbundle": "run-s terser prettier",
···
"bs-platform": "^4.0.17",
"bundlesize": "^0.17.0",
"coveralls": "^3.0.0",
+
"husky": "^1.3.1",
+
"lint-staged": "^8.1.5",
"microbundle": "^0.9.0",
"npm-run-all": "^4.1.5",
"prettier": "^1.15.3",
"rimraf": "^2.6.3",
"terser": "^3.14.1"
+
},
+
"lint-staged": {
+
"*.re": [
+
"bsrefmt --in-place",
+
"git add"
+
]
+
},
+
"husky": {
+
"hooks": {
+
"pre-commit": "lint-staged"
+
}
},
"prettier": {
"printWidth": 100
+70 -72
src/operators/wonka_operator_combine.re
···
open Wonka_helpers;
type combineStateT('a, 'b) = {
-
mutable talkbackA: (.talkbackT) => unit,
-
mutable talkbackB: (.talkbackT) => unit,
mutable lastValA: option('a),
mutable lastValB: option('b),
mutable gotSignal: bool,
···
mutable ended: bool,
};
-
let combine = sourceA => curry(sourceB => curry(sink => {
-
let state = {
-
talkbackA: talkbackPlaceholder,
-
talkbackB: talkbackPlaceholder,
-
lastValA: None,
-
lastValB: None,
-
gotSignal: false,
-
endCounter: 0,
-
ended: false
-
};
-
sourceA((.signal) => {
-
switch (signal, state.lastValB) {
-
| (Start(tb), _) => state.talkbackA = tb
-
| (Push(a), None) => {
-
state.lastValA = Some(a);
-
state.gotSignal = false;
-
}
-
| (Push(a), Some(b)) when !state.ended => {
-
state.lastValA = Some(a);
-
state.gotSignal = false;
-
sink(.Push((a, b)));
-
}
-
| (End, _) when state.endCounter < 1 =>
-
state.endCounter = state.endCounter + 1
-
| (End, _) when !state.ended => {
-
state.ended = true;
-
sink(.End);
-
}
-
| _ => ()
-
}
-
});
-
sourceB((.signal) => {
-
switch (signal, state.lastValA) {
-
| (Start(tb), _) => state.talkbackB = tb
-
| (Push(b), None) => {
-
state.lastValB = Some(b);
-
state.gotSignal = false;
-
}
-
| (Push(b), Some(a)) when !state.ended => {
-
state.lastValB = Some(b);
-
state.gotSignal = false;
-
sink(.Push((a, b)));
-
}
-
| (End, _) when state.endCounter < 1 =>
-
state.endCounter = state.endCounter + 1
-
| (End, _) when !state.ended => {
-
state.ended = true;
-
sink(.End);
-
}
-
| _ => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
if (!state.ended) {
-
switch (signal) {
-
| Close => {
-
state.ended = true;
-
state.talkbackA(.Close);
-
state.talkbackB(.Close);
-
}
-
| Pull when !state.gotSignal => {
-
state.gotSignal = true;
-
state.talkbackA(.signal);
-
state.talkbackB(.signal);
-
}
-
| Pull => ()
-
}
-
};
-
}));
-
}));
···
open Wonka_helpers;
type combineStateT('a, 'b) = {
+
mutable talkbackA: (. talkbackT) => unit,
+
mutable talkbackB: (. talkbackT) => unit,
mutable lastValA: option('a),
mutable lastValB: option('b),
mutable gotSignal: bool,
···
mutable ended: bool,
};
+
let combine = sourceA =>
+
curry(sourceB =>
+
curry(sink => {
+
let state = {
+
talkbackA: talkbackPlaceholder,
+
talkbackB: talkbackPlaceholder,
+
lastValA: None,
+
lastValB: None,
+
gotSignal: false,
+
endCounter: 0,
+
ended: false,
+
};
+
sourceA((. signal) =>
+
switch (signal, state.lastValB) {
+
| (Start(tb), _) => state.talkbackA = tb
+
| (Push(a), None) =>
+
state.lastValA = Some(a);
+
state.gotSignal = false;
+
| (Push(a), Some(b)) when !state.ended =>
+
state.lastValA = Some(a);
+
state.gotSignal = false;
+
sink(. Push((a, b)));
+
| (End, _) when state.endCounter < 1 =>
+
state.endCounter = state.endCounter + 1
+
| (End, _) when !state.ended =>
+
state.ended = true;
+
sink(. End);
+
| _ => ()
+
}
+
);
+
sourceB((. signal) =>
+
switch (signal, state.lastValA) {
+
| (Start(tb), _) => state.talkbackB = tb
+
| (Push(b), None) =>
+
state.lastValB = Some(b);
+
state.gotSignal = false;
+
| (Push(b), Some(a)) when !state.ended =>
+
state.lastValB = Some(b);
+
state.gotSignal = false;
+
sink(. Push((a, b)));
+
| (End, _) when state.endCounter < 1 =>
+
state.endCounter = state.endCounter + 1
+
| (End, _) when !state.ended =>
+
state.ended = true;
+
sink(. End);
+
| _ => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
if (!state.ended) {
+
switch (signal) {
+
| Close =>
+
state.ended = true;
+
state.talkbackA(. Close);
+
state.talkbackB(. Close);
+
| Pull when !state.gotSignal =>
+
state.gotSignal = true;
+
state.talkbackA(. signal);
+
state.talkbackB(. signal);
+
| Pull => ()
+
};
+
},
+
),
+
);
+
})
+
);
+80 -78
src/operators/wonka_operator_concatMap.re
···
type concatMapStateT('a) = {
inputQueue: Rebel.MutableQueue.t('a),
-
mutable outerTalkback: (.talkbackT) => unit,
-
mutable innerTalkback: (.talkbackT) => unit,
mutable innerActive: bool,
mutable closed: bool,
-
mutable ended: bool
};
-
let concatMap = f => curry(source => curry(sink => {
-
let state: concatMapStateT('a) = {
-
inputQueue: Rebel.MutableQueue.make(),
-
outerTalkback: talkbackPlaceholder,
-
innerTalkback: talkbackPlaceholder,
-
innerActive: false,
-
closed: false,
-
ended: false
-
};
-
let rec applyInnerSource = innerSource =>
-
innerSource((.signal) => {
-
switch (signal) {
-
| End => {
-
state.innerActive = false;
-
state.innerTalkback = talkbackPlaceholder;
-
switch (Rebel.MutableQueue.pop(state.inputQueue)) {
-
| Some(input) => applyInnerSource(f(.input))
-
| None when state.ended => sink(.End)
-
| None => ()
-
};
-
}
-
| Start(tb) => {
-
state.innerActive = true;
-
state.innerTalkback = tb;
-
tb(.Pull);
-
}
-
| Push(x) when !state.closed => {
-
sink(.Push(x));
-
state.innerTalkback(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
source((.signal) => {
-
switch (signal) {
-
| End when !state.ended => {
-
state.ended = true;
-
if (!state.innerActive && Rebel.MutableQueue.isEmpty(state.inputQueue)) {
-
sink(.End);
-
}
-
}
-
| End => ()
-
| Start(tb) => {
-
state.outerTalkback = tb;
-
tb(.Pull);
-
}
-
| Push(x) when !state.ended => {
-
if (state.innerActive) {
-
Rebel.MutableQueue.add(state.inputQueue, x);
-
} else {
-
applyInnerSource(f(.x));
-
}
-
state.outerTalkback(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => if (!state.ended) state.innerTalkback(.Pull)
-
| Close => {
-
state.innerTalkback(.Close);
-
if (!state.ended) {
-
state.ended = true;
-
state.closed = true;
-
state.outerTalkback(.Close);
-
state.innerTalkback = talkbackPlaceholder;
-
}
-
}
-
}
-
}));
-
}));
-
let concatAll = source => concatMap((.x) => x, source);
let concat = sources => {
-
open Wonka_source_fromArray;
-
concatMap((.x) => x, fromArray(sources));
};
···
type concatMapStateT('a) = {
inputQueue: Rebel.MutableQueue.t('a),
+
mutable outerTalkback: (. talkbackT) => unit,
+
mutable innerTalkback: (. talkbackT) => unit,
mutable innerActive: bool,
mutable closed: bool,
+
mutable ended: bool,
};
+
let concatMap = f =>
+
curry(source =>
+
curry(sink => {
+
let state: concatMapStateT('a) = {
+
inputQueue: Rebel.MutableQueue.make(),
+
outerTalkback: talkbackPlaceholder,
+
innerTalkback: talkbackPlaceholder,
+
innerActive: false,
+
closed: false,
+
ended: false,
+
};
+
let rec applyInnerSource = innerSource =>
+
innerSource((. signal) =>
+
switch (signal) {
+
| End =>
+
state.innerActive = false;
+
state.innerTalkback = talkbackPlaceholder;
+
switch (Rebel.MutableQueue.pop(state.inputQueue)) {
+
| Some(input) => applyInnerSource(f(. input))
+
| None when state.ended => sink(. End)
+
| None => ()
+
};
+
| Start(tb) =>
+
state.innerActive = true;
+
state.innerTalkback = tb;
+
tb(. Pull);
+
| Push(x) when !state.closed =>
+
sink(. Push(x));
+
state.innerTalkback(. Pull);
+
| Push(_) => ()
+
}
+
);
+
source((. signal) =>
+
switch (signal) {
+
| End when !state.ended =>
+
state.ended = true;
+
if (!state.innerActive
+
&& Rebel.MutableQueue.isEmpty(state.inputQueue)) {
+
sink(. End);
+
};
+
| End => ()
+
| Start(tb) =>
+
state.outerTalkback = tb;
+
tb(. Pull);
+
| Push(x) when !state.ended =>
+
if (state.innerActive) {
+
Rebel.MutableQueue.add(state.inputQueue, x);
+
} else {
+
applyInnerSource(f(. x));
+
};
+
state.outerTalkback(. Pull);
+
| Push(_) => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
if (!state.ended) {
+
state.innerTalkback(. Pull);
+
}
+
| Close =>
+
state.innerTalkback(. Close);
+
if (!state.ended) {
+
state.ended = true;
+
state.closed = true;
+
state.outerTalkback(. Close);
+
state.innerTalkback = talkbackPlaceholder;
+
};
+
},
+
),
+
);
+
})
+
);
+
let concatAll = source => concatMap((. x) => x, source);
let concat = sources => {
+
Wonka_source_fromArray.(concatMap((. x) => x, fromArray(sources)));
};
+11 -8
src/operators/wonka_operator_filter.re
···
open Wonka_types;
open Wonka_helpers;
-
let filter = f => curry(source => curry(sink => {
-
captureTalkback(source, (.signal, talkback) => {
-
switch (signal) {
-
| Push(x) when !f(.x) => talkback(.Pull)
-
| _ => sink(.signal)
-
}
-
});
-
}));
···
open Wonka_types;
open Wonka_helpers;
+
let filter = f =>
+
curry(source =>
+
curry(sink =>
+
captureTalkback(source, (. signal, talkback) =>
+
switch (signal) {
+
| Push(x) when !f(. x) => talkback(. Pull)
+
| _ => sink(. signal)
+
}
+
)
+
)
+
);
+14 -9
src/operators/wonka_operator_map.re
···
open Wonka_types;
-
let map = f => curry(source => curry(sink => {
-
source((.signal) => sink(.
-
switch (signal) {
-
| Start(x) => Start(x)
-
| Push(x) => Push(f(.x))
-
| End => End
-
}
-
));
-
}));
···
open Wonka_types;
+
let map = f =>
+
curry(source =>
+
curry(sink =>
+
source((. signal) =>
+
sink(.
+
switch (signal) {
+
| Start(x) => Start(x)
+
| Push(x) => Push(f(. x))
+
| End => End
+
},
+
)
+
)
+
)
+
);
+78 -72
src/operators/wonka_operator_mergeMap.re
···
open Wonka_helpers;
type mergeMapStateT = {
-
mutable outerTalkback: (.talkbackT) => unit,
-
mutable innerTalkbacks: Rebel.Array.t((.talkbackT) => unit),
-
mutable ended: bool
};
-
let mergeMap = f => curry(source => curry(sink => {
-
let state: mergeMapStateT = {
-
outerTalkback: talkbackPlaceholder,
-
innerTalkbacks: Rebel.Array.makeEmpty(),
-
ended: false
-
};
-
let applyInnerSource = innerSource => {
-
let talkback = ref(talkbackPlaceholder);
-
innerSource((.signal) => {
-
switch (signal) {
-
| End => {
-
state.innerTalkbacks = Rebel.Array.filter(state.innerTalkbacks, x => x !== talkback^);
-
if (state.ended && Rebel.Array.size(state.innerTalkbacks) === 0) {
-
sink(.End);
-
}
-
}
-
| Start(tb) => {
-
talkback := tb;
-
state.innerTalkbacks = Rebel.Array.append(state.innerTalkbacks, tb);
-
tb(.Pull);
-
}
-
| Push(x) when Rebel.Array.size(state.innerTalkbacks) !== 0 => {
-
sink(.Push(x));
-
talkback^(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
};
-
source((.signal) => {
-
switch (signal) {
-
| End when !state.ended => {
-
state.ended = true;
-
if (Rebel.Array.size(state.innerTalkbacks) === 0) {
-
sink(.End);
-
}
-
}
-
| End => ()
-
| Start(tb) => {
-
state.outerTalkback = tb;
-
tb(.Pull);
-
}
-
| Push(x) when !state.ended => {
-
applyInnerSource(f(.x));
-
state.outerTalkback(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => {
-
Rebel.Array.forEach(state.innerTalkbacks, talkback => talkback(.Close));
-
if (!state.ended) {
-
state.ended = true;
-
state.outerTalkback(.Close);
-
Rebel.Array.forEach(state.innerTalkbacks, talkback => talkback(.Close));
-
state.innerTalkbacks = Rebel.Array.makeEmpty();
-
}
-
}
-
| Pull when !state.ended =>
-
Rebel.Array.forEach(state.innerTalkbacks, talkback => talkback(.Pull));
-
| Pull => ()
-
}
-
}));
-
}));
let merge = sources => {
-
open Wonka_source_fromArray;
-
mergeMap((.x) => x, fromArray(sources));
};
-
let mergeAll = source => mergeMap((.x) => x, source);
let flatten = mergeAll;
···
open Wonka_helpers;
type mergeMapStateT = {
+
mutable outerTalkback: (. talkbackT) => unit,
+
mutable innerTalkbacks: Rebel.Array.t((. talkbackT) => unit),
+
mutable ended: bool,
};
+
let mergeMap = f =>
+
curry(source =>
+
curry(sink => {
+
let state: mergeMapStateT = {
+
outerTalkback: talkbackPlaceholder,
+
innerTalkbacks: Rebel.Array.makeEmpty(),
+
ended: false,
+
};
+
let applyInnerSource = innerSource => {
+
let talkback = ref(talkbackPlaceholder);
+
innerSource((. signal) =>
+
switch (signal) {
+
| End =>
+
state.innerTalkbacks =
+
Rebel.Array.filter(state.innerTalkbacks, x => x !== talkback^);
+
if (state.ended && Rebel.Array.size(state.innerTalkbacks) === 0) {
+
sink(. End);
+
};
+
| Start(tb) =>
+
talkback := tb;
+
state.innerTalkbacks =
+
Rebel.Array.append(state.innerTalkbacks, tb);
+
tb(. Pull);
+
| Push(x) when Rebel.Array.size(state.innerTalkbacks) !== 0 =>
+
sink(. Push(x));
+
talkback^(. Pull);
+
| Push(_) => ()
+
}
+
);
+
};
+
source((. signal) =>
+
switch (signal) {
+
| End when !state.ended =>
+
state.ended = true;
+
if (Rebel.Array.size(state.innerTalkbacks) === 0) {
+
sink(. End);
+
};
+
| End => ()
+
| Start(tb) =>
+
state.outerTalkback = tb;
+
tb(. Pull);
+
| Push(x) when !state.ended =>
+
applyInnerSource(f(. x));
+
state.outerTalkback(. Pull);
+
| Push(_) => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
Rebel.Array.forEach(state.innerTalkbacks, talkback =>
+
talkback(. Close)
+
);
+
if (!state.ended) {
+
state.ended = true;
+
state.outerTalkback(. Close);
+
Rebel.Array.forEach(state.innerTalkbacks, talkback =>
+
talkback(. Close)
+
);
+
state.innerTalkbacks = Rebel.Array.makeEmpty();
+
};
+
| Pull when !state.ended =>
+
Rebel.Array.forEach(state.innerTalkbacks, talkback =>
+
talkback(. Pull)
+
)
+
| Pull => ()
+
},
+
),
+
);
+
})
+
);
let merge = sources => {
+
Wonka_source_fromArray.(mergeMap((. x) => x, fromArray(sources)));
};
+
let mergeAll = source => mergeMap((. x) => x, source);
let flatten = mergeAll;
+28 -25
src/operators/wonka_operator_onEnd.re
···
open Wonka_types;
-
let onEnd = f => curry(source => curry(sink => {
-
let ended = ref(false);
-
source((.signal) => {
-
switch (signal) {
-
| Start(talkback) => {
-
sink(.Start((.signal) => {
switch (signal) {
-
| Close when !ended^ => {
-
ended := true;
-
f(.);
}
-
| Close => ()
-
| Pull => talkback(.Pull)
-
}
-
}));
-
}
-
| End => {
-
if (!ended^) {
-
ended := true;
-
sink(.signal);
-
f(.);
-
}
-
}
-
| _ => sink(.signal)
-
};
-
});
-
}));
···
open Wonka_types;
+
let onEnd = f =>
+
curry(source =>
+
curry(sink => {
+
let ended = ref(false);
+
source((. signal) =>
switch (signal) {
+
| Start(talkback) =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close when ! ended^ =>
+
ended := true;
+
f(.);
+
| Close => ()
+
| Pull => talkback(. Pull)
+
},
+
),
+
)
+
| End =>
+
if (! ended^) {
+
ended := true;
+
sink(. signal);
+
f(.);
+
}
+
| _ => sink(. signal)
}
+
);
+
})
+
);
+12 -9
src/operators/wonka_operator_onPush.re
···
open Wonka_types;
-
let onPush = f => curry(source => curry(sink => {
-
source((.signal) => {
-
switch (signal) {
-
| Push(x) => f(.x)
-
| _ => ()
-
};
-
sink(.signal);
-
});
-
}));
let tap = onPush;
···
open Wonka_types;
+
let onPush = f =>
+
curry(source =>
+
curry(sink =>
+
source((. signal) => {
+
switch (signal) {
+
| Push(x) => f(. x)
+
| _ => ()
+
};
+
sink(. signal);
+
})
+
)
+
);
let tap = onPush;
+13 -11
src/operators/wonka_operator_onStart.re
···
open Wonka_types;
-
let onStart = f => curry(source => curry(sink => {
-
source((.signal) => {
-
switch (signal) {
-
| Start(_) => {
-
sink(.signal);
-
f(.);
-
}
-
| _ => sink(.signal)
-
};
-
});
-
}));
···
open Wonka_types;
+
let onStart = f =>
+
curry(source =>
+
curry(sink =>
+
source((. signal) =>
+
switch (signal) {
+
| Start(_) =>
+
sink(. signal);
+
f(.);
+
| _ => sink(. signal)
+
}
+
)
+
)
+
);
+17 -13
src/operators/wonka_operator_scan.re
···
open Wonka_types;
-
let scan = (f, seed) => curry(source => curry(sink => {
-
let acc = ref(seed);
-
source((.signal) => sink(.
-
switch (signal) {
-
| Push(x) => {
-
acc := f(.acc^, x);
-
Push(acc^)
-
}
-
| Start(x) => Start(x)
-
| End => End
-
}
-
));
-
}));
···
open Wonka_types;
+
let scan = (f, seed) =>
+
curry(source =>
+
curry(sink => {
+
let acc = ref(seed);
+
source((. signal) =>
+
sink(.
+
switch (signal) {
+
| Push(x) =>
+
acc := f(. acc^, x);
+
Push(acc^);
+
| Start(x) => Start(x)
+
| End => End
+
},
+
)
+
);
+
})
+
);
+26 -27
src/operators/wonka_operator_share.re
···
type shareStateT('a) = {
mutable sinks: Rebel.Array.t(sinkT('a)),
-
mutable talkback: (.talkbackT) => unit,
-
mutable gotSignal: bool
};
let share = source => {
let state = {
sinks: Rebel.Array.makeEmpty(),
talkback: talkbackPlaceholder,
-
gotSignal: false
};
sink => {
state.sinks = Rebel.Array.append(state.sinks, sink);
if (Rebel.Array.size(state.sinks) === 1) {
-
source((.signal) => {
switch (signal) {
-
| Push(_) => {
state.gotSignal = false;
-
Rebel.Array.forEach(state.sinks, sink => sink(.signal));
-
}
| Start(x) => state.talkback = x
-
| End => {
-
Rebel.Array.forEach(state.sinks, sink => sink(.End));
state.sinks = Rebel.Array.makeEmpty();
}
-
}
-
});
};
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => {
-
state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink);
-
if (Rebel.Array.size(state.sinks) === 0) {
-
state.talkback(.Close);
-
};
-
}
-
| Pull when !state.gotSignal => {
-
state.gotSignal = true;
-
state.talkback(.signal);
-
}
-
| Pull => ()
-
}
-
}));
-
}
};
···
type shareStateT('a) = {
mutable sinks: Rebel.Array.t(sinkT('a)),
+
mutable talkback: (. talkbackT) => unit,
+
mutable gotSignal: bool,
};
let share = source => {
let state = {
sinks: Rebel.Array.makeEmpty(),
talkback: talkbackPlaceholder,
+
gotSignal: false,
};
sink => {
state.sinks = Rebel.Array.append(state.sinks, sink);
if (Rebel.Array.size(state.sinks) === 1) {
+
source((. signal) =>
switch (signal) {
+
| Push(_) =>
state.gotSignal = false;
+
Rebel.Array.forEach(state.sinks, sink => sink(. signal));
| Start(x) => state.talkback = x
+
| End =>
+
Rebel.Array.forEach(state.sinks, sink => sink(. End));
state.sinks = Rebel.Array.makeEmpty();
}
+
);
};
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink);
+
if (Rebel.Array.size(state.sinks) === 0) {
+
state.talkback(. Close);
+
};
+
| Pull when !state.gotSignal =>
+
state.gotSignal = true;
+
state.talkback(. signal);
+
| Pull => ()
+
},
+
),
+
);
+
};
};
+14 -12
src/operators/wonka_operator_skip.re
···
open Wonka_types;
open Wonka_helpers;
-
let skip = wait => curry(source => curry(sink => {
-
let rest = ref(wait);
-
captureTalkback(source, (.signal, talkback) => {
-
switch (signal) {
-
| Push(_) when rest^ > 0 => {
-
rest := rest^ - 1;
-
talkback(.Pull);
-
}
-
| _ => sink(.signal)
-
}
-
});
-
}));
···
open Wonka_types;
open Wonka_helpers;
+
let skip = wait =>
+
curry(source =>
+
curry(sink => {
+
let rest = ref(wait);
+
captureTalkback(source, (. signal, talkback) =>
+
switch (signal) {
+
| Push(_) when rest^ > 0 =>
+
rest := rest^ - 1;
+
talkback(. Pull);
+
| _ => sink(. signal)
+
}
+
);
+
})
+
);
+60 -56
src/operators/wonka_operator_skipUntil.re
···
mutable skip: bool,
mutable ended: bool,
mutable gotSignal: bool,
-
mutable sourceTalkback: (.talkbackT) => unit,
-
mutable notifierTalkback: (.talkbackT) => unit
};
-
let skipUntil = notifier => curry(source => curry(sink => {
-
let state: skipUntilStateT = {
-
skip: true,
-
ended: false,
-
gotSignal: false,
-
sourceTalkback: talkbackPlaceholder,
-
notifierTalkback: talkbackPlaceholder
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => {
-
state.sourceTalkback = tb;
-
-
notifier((.signal) => {
switch (signal) {
-
| Start(innerTb) => {
-
state.notifierTalkback = innerTb;
-
innerTb(.Pull);
-
tb(.Pull);
-
}
-
| Push(_) => {
-
state.skip = false;
-
state.notifierTalkback(.Close);
-
}
-
| End => ()
}
-
});
-
}
-
| Push(_) when state.skip && !state.ended => state.sourceTalkback(.Pull)
-
| Push(_) when !state.ended => {
-
state.gotSignal = false;
-
sink(.signal)
-
}
-
| Push(_) => ()
-
| End => {
-
if (state.skip) state.notifierTalkback(.Close);
-
state.ended = true;
-
sink(.End)
-
}
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => {
-
if (state.skip) state.notifierTalkback(.Close);
-
state.ended = true;
-
state.sourceTalkback(.Close);
-
}
-
| Pull when !state.gotSignal && !state.ended => {
-
state.gotSignal = true;
-
state.sourceTalkback(.Pull);
-
}
-
| Pull => ()
-
}
-
}));
-
}));
···
mutable skip: bool,
mutable ended: bool,
mutable gotSignal: bool,
+
mutable sourceTalkback: (. talkbackT) => unit,
+
mutable notifierTalkback: (. talkbackT) => unit,
};
+
let skipUntil = notifier =>
+
curry(source =>
+
curry(sink => {
+
let state: skipUntilStateT = {
+
skip: true,
+
ended: false,
+
gotSignal: false,
+
sourceTalkback: talkbackPlaceholder,
+
notifierTalkback: talkbackPlaceholder,
+
};
+
source((. signal) =>
switch (signal) {
+
| Start(tb) =>
+
state.sourceTalkback = tb;
+
+
notifier((. signal) =>
+
switch (signal) {
+
| Start(innerTb) =>
+
state.notifierTalkback = innerTb;
+
innerTb(. Pull);
+
tb(. Pull);
+
| Push(_) =>
+
state.skip = false;
+
state.notifierTalkback(. Close);
+
| End => ()
+
}
+
);
+
| Push(_) when state.skip && !state.ended =>
+
state.sourceTalkback(. Pull)
+
| Push(_) when !state.ended =>
+
state.gotSignal = false;
+
sink(. signal);
+
| Push(_) => ()
+
| End =>
+
if (state.skip) {
+
state.notifierTalkback(. Close);
+
};
+
state.ended = true;
+
sink(. End);
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
if (state.skip) {
+
state.notifierTalkback(. Close);
+
};
+
state.ended = true;
+
state.sourceTalkback(. Close);
+
| Pull when !state.gotSignal && !state.ended =>
+
state.gotSignal = true;
+
state.sourceTalkback(. Pull);
+
| Pull => ()
+
},
+
),
+
);
+
})
+
);
+18 -16
src/operators/wonka_operator_skipWhile.re
···
open Wonka_types;
open Wonka_helpers;
-
let skipWhile = f => curry(source => curry(sink => {
-
let skip = ref(true);
-
captureTalkback(source, (.signal, talkback) => {
-
switch (signal) {
-
| Push(x) when skip^ => {
-
if (f(.x)) {
-
talkback(.Pull);
-
} else {
-
skip := false;
-
sink(.signal);
-
};
-
}
-
| _ => sink(.signal)
-
}
-
});
-
}));
···
open Wonka_types;
open Wonka_helpers;
+
let skipWhile = f =>
+
curry(source =>
+
curry(sink => {
+
let skip = ref(true);
+
captureTalkback(source, (. signal, talkback) =>
+
switch (signal) {
+
| Push(x) when skip^ =>
+
if (f(. x)) {
+
talkback(. Pull);
+
} else {
+
skip := false;
+
sink(. signal);
+
}
+
| _ => sink(. signal)
+
}
+
);
+
})
+
);
+72 -69
src/operators/wonka_operator_switchMap.re
···
open Wonka_helpers;
type switchMapStateT('a) = {
-
mutable outerTalkback: (.talkbackT) => unit,
-
mutable innerTalkback: (.talkbackT) => unit,
mutable innerActive: bool,
mutable closed: bool,
-
mutable ended: bool
};
-
let switchMap = f => curry(source => curry(sink => {
-
let state: switchMapStateT('a) = {
-
outerTalkback: talkbackPlaceholder,
-
innerTalkback: talkbackPlaceholder,
-
innerActive: false,
-
closed: false,
-
ended: false
-
};
-
let applyInnerSource = innerSource =>
-
innerSource((.signal) => {
-
switch (signal) {
-
| End => {
-
state.innerActive = false;
-
state.innerTalkback = talkbackPlaceholder;
-
if (state.ended) sink(.End);
-
}
-
| Start(tb) => {
-
state.innerActive = true;
-
state.innerTalkback = tb;
-
tb(.Pull);
-
}
-
| Push(x) when !state.closed => {
-
sink(.Push(x));
-
state.innerTalkback(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
source((.signal) => {
-
switch (signal) {
-
| End when !state.ended => {
-
state.ended = true;
-
if (!state.innerActive) sink(.End);
-
}
-
| End => ()
-
| Start(tb) => {
-
state.outerTalkback = tb;
-
tb(.Pull);
-
}
-
| Push(x) when !state.ended => {
-
if (state.innerActive) {
-
state.innerTalkback(.Close);
-
state.innerTalkback = talkbackPlaceholder;
-
}
-
applyInnerSource(f(.x));
-
state.outerTalkback(.Pull);
-
}
-
| Push(_) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => state.innerTalkback(.Pull)
-
| Close => {
-
state.innerTalkback(.Close);
-
if (!state.ended) {
-
state.ended = true;
-
state.closed = true;
-
state.outerTalkback(.Close);
-
state.innerTalkback = talkbackPlaceholder;
-
}
-
}
-
}
-
}));
-
}));
-
let switchAll = source => switchMap((.x) => x, source);
···
open Wonka_helpers;
type switchMapStateT('a) = {
+
mutable outerTalkback: (. talkbackT) => unit,
+
mutable innerTalkback: (. talkbackT) => unit,
mutable innerActive: bool,
mutable closed: bool,
+
mutable ended: bool,
};
+
let switchMap = f =>
+
curry(source =>
+
curry(sink => {
+
let state: switchMapStateT('a) = {
+
outerTalkback: talkbackPlaceholder,
+
innerTalkback: talkbackPlaceholder,
+
innerActive: false,
+
closed: false,
+
ended: false,
+
};
+
let applyInnerSource = innerSource =>
+
innerSource((. signal) =>
+
switch (signal) {
+
| End =>
+
state.innerActive = false;
+
state.innerTalkback = talkbackPlaceholder;
+
if (state.ended) {
+
sink(. End);
+
};
+
| Start(tb) =>
+
state.innerActive = true;
+
state.innerTalkback = tb;
+
tb(. Pull);
+
| Push(x) when !state.closed =>
+
sink(. Push(x));
+
state.innerTalkback(. Pull);
+
| Push(_) => ()
+
}
+
);
+
source((. signal) =>
+
switch (signal) {
+
| End when !state.ended =>
+
state.ended = true;
+
if (!state.innerActive) {
+
sink(. End);
+
};
+
| End => ()
+
| Start(tb) =>
+
state.outerTalkback = tb;
+
tb(. Pull);
+
| Push(x) when !state.ended =>
+
if (state.innerActive) {
+
state.innerTalkback(. Close);
+
state.innerTalkback = talkbackPlaceholder;
+
};
+
applyInnerSource(f(. x));
+
state.outerTalkback(. Pull);
+
| Push(_) => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull => state.innerTalkback(. Pull)
+
| Close =>
+
state.innerTalkback(. Close);
+
if (!state.ended) {
+
state.ended = true;
+
state.closed = true;
+
state.outerTalkback(. Close);
+
state.innerTalkback = talkbackPlaceholder;
+
};
+
},
+
),
+
);
+
})
+
);
+
let switchAll = source => switchMap((. x) => x, source);
+37 -37
src/operators/wonka_operator_take.re
···
type takeStateT = {
mutable taken: int,
-
mutable talkback: (.talkbackT) => unit
};
-
let take = max => curry(source => curry(sink => {
-
let state: takeStateT = {
-
taken: 0,
-
talkback: talkbackPlaceholder
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => state.talkback = tb;
-
| Push(_) when state.taken < max => {
-
state.taken = state.taken + 1;
-
sink(.signal);
-
if (state.taken === max) {
-
sink(.End);
-
state.talkback(.Close);
-
};
-
}
-
| Push(_) => ()
-
| End when state.taken < max => {
-
state.taken = max;
-
sink(.End)
-
}
-
| End => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
if (state.taken < max) {
-
switch (signal) {
-
| Pull => state.talkback(.Pull);
-
| Close => {
-
state.taken = max;
-
state.talkback(.Close);
-
}
-
}
-
};
-
}));
-
}));
···
type takeStateT = {
mutable taken: int,
+
mutable talkback: (. talkbackT) => unit,
};
+
let take = max =>
+
curry(source =>
+
curry(sink => {
+
let state: takeStateT = {taken: 0, talkback: talkbackPlaceholder};
+
source((. signal) =>
+
switch (signal) {
+
| Start(tb) => state.talkback = tb
+
| Push(_) when state.taken < max =>
+
state.taken = state.taken + 1;
+
sink(. signal);
+
if (state.taken === max) {
+
sink(. End);
+
state.talkback(. Close);
+
};
+
| Push(_) => ()
+
| End when state.taken < max =>
+
state.taken = max;
+
sink(. End);
+
| End => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
if (state.taken < max) {
+
switch (signal) {
+
| Pull => state.talkback(. Pull)
+
| Close =>
+
state.taken = max;
+
state.talkback(. Close);
+
};
+
},
+
),
+
);
+
})
+
);
+20 -18
src/operators/wonka_operator_takeLast.re
···
open Wonka_types;
open Wonka_helpers;
-
let takeLast = max => curry(source => curry(sink => {
-
open Rebel;
-
let queue = MutableQueue.make();
-
captureTalkback(source, (.signal, talkback) => {
-
switch (signal) {
-
| Start(_) => talkback(.Pull)
-
| Push(x) => {
-
let size = MutableQueue.size(queue);
-
if (size >= max && max > 0) {
-
ignore(MutableQueue.pop(queue));
-
};
-
MutableQueue.add(queue, x);
-
talkback(.Pull);
-
}
-
| End => makeTrampoline(sink, (.) => MutableQueue.pop(queue))
-
}
-
});
-
}));
···
open Wonka_types;
open Wonka_helpers;
+
let takeLast = max =>
+
curry(source =>
+
curry(sink => {
+
open Rebel;
+
let queue = MutableQueue.make();
+
captureTalkback(source, (. signal, talkback) =>
+
switch (signal) {
+
| Start(_) => talkback(. Pull)
+
| Push(x) =>
+
let size = MutableQueue.size(queue);
+
if (size >= max && max > 0) {
+
ignore(MutableQueue.pop(queue));
+
};
+
MutableQueue.add(queue, x);
+
talkback(. Pull);
+
| End => makeTrampoline(sink, (.) => MutableQueue.pop(queue))
+
}
+
);
+
})
+
);
+48 -47
src/operators/wonka_operator_takeUntil.re
···
type takeUntilStateT = {
mutable ended: bool,
-
mutable sourceTalkback: (.talkbackT) => unit,
-
mutable notifierTalkback: (.talkbackT) => unit
};
-
let takeUntil = notifier => curry(source => curry(sink => {
-
let state: takeUntilStateT = {
-
ended: false,
-
sourceTalkback: talkbackPlaceholder,
-
notifierTalkback: talkbackPlaceholder
-
};
-
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => {
-
state.sourceTalkback = tb;
-
notifier((.signal) => {
switch (signal) {
-
| Start(innerTb) => {
-
state.notifierTalkback = innerTb;
-
innerTb(.Pull);
-
}
-
| Push(_) => {
state.ended = true;
-
state.notifierTalkback(.Close);
-
state.sourceTalkback(.Close);
-
sink(.End);
-
}
| End => ()
}
-
});
-
}
-
| End when !state.ended => {
-
state.notifierTalkback(.Close);
-
state.ended = true;
-
sink(.End);
-
}
-
| End => ()
-
| Push(_) when !state.ended => sink(.signal)
-
| Push(_) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
if (!state.ended) {
-
switch (signal) {
-
| Close => {
-
state.sourceTalkback(.Close);
-
state.notifierTalkback(.Close);
-
}
-
| Pull => state.sourceTalkback(.Pull)
-
}
-
};
-
}));
-
}));
···
type takeUntilStateT = {
mutable ended: bool,
+
mutable sourceTalkback: (. talkbackT) => unit,
+
mutable notifierTalkback: (. talkbackT) => unit,
};
+
let takeUntil = notifier =>
+
curry(source =>
+
curry(sink => {
+
let state: takeUntilStateT = {
+
ended: false,
+
sourceTalkback: talkbackPlaceholder,
+
notifierTalkback: talkbackPlaceholder,
+
};
+
source((. signal) =>
switch (signal) {
+
| Start(tb) =>
+
state.sourceTalkback = tb;
+
+
notifier((. signal) =>
+
switch (signal) {
+
| Start(innerTb) =>
+
state.notifierTalkback = innerTb;
+
innerTb(. Pull);
+
| Push(_) =>
+
state.ended = true;
+
state.notifierTalkback(. Close);
+
state.sourceTalkback(. Close);
+
sink(. End);
+
| End => ()
+
}
+
);
+
| End when !state.ended =>
+
state.notifierTalkback(. Close);
state.ended = true;
+
sink(. End);
| End => ()
+
| Push(_) when !state.ended => sink(. signal)
+
| Push(_) => ()
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
if (!state.ended) {
+
switch (signal) {
+
| Close =>
+
state.sourceTalkback(. Close);
+
state.notifierTalkback(. Close);
+
| Pull => state.sourceTalkback(. Pull)
+
};
+
},
+
),
+
);
+
})
+
);
+40 -38
src/operators/wonka_operator_takeWhile.re
···
open Wonka_types;
open Wonka_helpers;
-
let takeWhile = f => curry(source => curry(sink => {
-
let ended = ref(false);
-
let talkback = ref(talkbackPlaceholder);
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => {
-
talkback := tb;
-
sink(.signal);
-
}
-
| End when !ended^ => {
-
ended := true;
-
sink(.End);
-
}
-
| End => ()
-
| Push(x) when !ended^ => {
-
if (!f(.x)) {
-
ended := true;
-
sink(.End);
-
talkback^(.Close);
-
} else {
-
sink(.signal);
-
};
-
}
-
| Push(_) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
if (!ended^) {
-
switch (signal) {
-
| Pull => talkback^(.Pull);
-
| Close => {
-
ended := true;
-
talkback^(.Close);
-
}
-
}
-
};
-
}));
-
}));
···
open Wonka_types;
open Wonka_helpers;
+
let takeWhile = f =>
+
curry(source =>
+
curry(sink => {
+
let ended = ref(false);
+
let talkback = ref(talkbackPlaceholder);
+
source((. signal) =>
+
switch (signal) {
+
| Start(tb) =>
+
talkback := tb;
+
sink(. signal);
+
| End when ! ended^ =>
+
ended := true;
+
sink(. End);
+
| End => ()
+
| Push(x) when ! ended^ =>
+
if (!f(. x)) {
+
ended := true;
+
sink(. End);
+
talkback^(. Close);
+
} else {
+
sink(. signal);
+
}
+
| Push(_) => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
if (! ended^) {
+
switch (signal) {
+
| Pull => talkback^(. Pull)
+
| Close =>
+
ended := true;
+
talkback^(. Close);
+
};
+
},
+
),
+
);
+
})
+
);
+15 -16
src/sinks/wonka_sink_publish.re
···
open Wonka_helpers;
type publishStateT = {
-
mutable talkback: (.talkbackT) => unit,
-
mutable ended: bool
};
let publish = source => {
-
let state: publishStateT = {
-
talkback: talkbackPlaceholder,
-
ended: false
-
};
-
source((.signal) => {
switch (signal) {
-
| Start(x) => {
state.talkback = x;
-
x(.Pull);
-
}
-
| Push(_) => if (!state.ended) state.talkback(.Pull);
-
| End => state.ended = true;
}
-
});
{
unsubscribe: () =>
if (!state.ended) {
state.ended = true;
-
state.talkback(.Close);
-
}
-
}
};
···
open Wonka_helpers;
type publishStateT = {
+
mutable talkback: (. talkbackT) => unit,
+
mutable ended: bool,
};
let publish = source => {
+
let state: publishStateT = {talkback: talkbackPlaceholder, ended: false};
+
source((. signal) =>
switch (signal) {
+
| Start(x) =>
state.talkback = x;
+
x(. Pull);
+
| Push(_) =>
+
if (!state.ended) {
+
state.talkback(. Pull);
+
}
+
| End => state.ended = true
}
+
);
{
unsubscribe: () =>
if (!state.ended) {
state.ended = true;
+
state.talkback(. Close);
+
},
+
};
};
+29 -32
src/sinks/wonka_sink_subscribe.re
···
open Wonka_helpers;
type subscribeStateT = {
-
mutable talkback: (.talkbackT) => unit,
-
mutable ended: bool
};
-
let subscribe = f => curry(source => {
-
let state: subscribeStateT = {
-
talkback: talkbackPlaceholder,
-
ended: false
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(x) => {
-
state.talkback = x;
-
x(.Pull);
-
}
-
| Push(x) when !state.ended => {
-
f(.x);
-
state.talkback(.Pull);
-
}
-
| Push(_) => ()
-
| End => state.ended = true;
-
}
});
-
{
-
unsubscribe: () =>
-
if (!state.ended) {
-
state.ended = true;
-
state.talkback(.Close);
-
}
-
}
-
});
-
-
let forEach = f => curry(source => {
-
ignore(subscribe(f, source));
-
});
···
open Wonka_helpers;
type subscribeStateT = {
+
mutable talkback: (. talkbackT) => unit,
+
mutable ended: bool,
};
+
let subscribe = f =>
+
curry(source => {
+
let state: subscribeStateT = {
+
talkback: talkbackPlaceholder,
+
ended: false,
+
};
+
+
source((. signal) =>
+
switch (signal) {
+
| Start(x) =>
+
state.talkback = x;
+
x(. Pull);
+
| Push(x) when !state.ended =>
+
f(. x);
+
state.talkback(. Pull);
+
| Push(_) => ()
+
| End => state.ended = true
+
}
+
);
+
{
+
unsubscribe: () =>
+
if (!state.ended) {
+
state.ended = true;
+
state.talkback(. Close);
+
},
+
};
});
+
let forEach = f => curry(source => ignore(subscribe(f, source)));
+31 -33
src/sources/wonka_source_fromArray.re
···
mutable index: int,
mutable ended: bool,
mutable looping: bool,
-
mutable pull: bool
};
-
let fromArray = arr => curry(sink => {
-
let size = Rebel.Array.size(arr);
-
let state = {
-
index: 0,
-
ended: false,
-
looping: false,
-
pull: false
-
};
-
sink(.Start((.signal) => {
-
switch (signal, state.looping) {
-
| (Pull, false) => {
-
state.pull = true;
-
state.looping = true;
-
while (state.pull && !state.ended) {
-
let index = state.index;
-
if (index < size) {
-
let x = Rebel.Array.getUnsafe(arr, index);
-
state.index = index + 1;
-
state.pull = false;
-
sink(.Push(x));
-
} else {
-
state.ended = true;
-
sink(.End);
-
}
-
};
-
state.looping = false;
-
}
-
| (Pull, true) => state.pull = true
-
| (Close, _) => state.ended = true
-
}
-
}));
-
});
···
mutable index: int,
mutable ended: bool,
mutable looping: bool,
+
mutable pull: bool,
};
+
let fromArray = arr =>
+
curry(sink => {
+
let size = Rebel.Array.size(arr);
+
let state = {index: 0, ended: false, looping: false, pull: false};
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal, state.looping) {
+
| (Pull, false) =>
+
state.pull = true;
+
state.looping = true;
+
while (state.pull && !state.ended) {
+
let index = state.index;
+
if (index < size) {
+
let x = Rebel.Array.getUnsafe(arr, index);
+
state.index = index + 1;
+
state.pull = false;
+
sink(. Push(x));
+
} else {
+
state.ended = true;
+
sink(. End);
+
};
+
};
+
state.looping = false;
+
| (Pull, true) => state.pull = true
+
| (Close, _) => state.ended = true
+
},
+
),
+
);
+
});
+29 -33
src/sources/wonka_source_fromList.re
···
mutable value: 'a,
mutable ended: bool,
mutable looping: bool,
-
mutable pull: bool
};
-
let fromList = ls => curry(sink => {
-
let state = {
-
value: ls,
-
ended: false,
-
looping: false,
-
pull: false
-
};
-
sink(.Start((.signal) => {
-
switch (signal, state.looping) {
-
| (Pull, false) => {
-
state.pull = true;
-
state.looping = true;
-
while (state.pull && !state.ended) {
-
switch (state.value) {
-
| [x, ...rest] => {
-
state.value = rest;
-
state.pull = false;
-
sink(.Push(x));
-
}
-
| [] => {
-
state.ended = true;
-
sink(.End);
-
}
-
}
-
};
-
state.looping = false;
-
}
-
| (Pull, true) => state.pull = true
-
| (Close, _) => state.ended = true
-
}
-
}));
-
});
···
mutable value: 'a,
mutable ended: bool,
mutable looping: bool,
+
mutable pull: bool,
};
+
let fromList = ls =>
+
curry(sink => {
+
let state = {value: ls, ended: false, looping: false, pull: false};
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal, state.looping) {
+
| (Pull, false) =>
+
state.pull = true;
+
state.looping = true;
+
while (state.pull && !state.ended) {
+
switch (state.value) {
+
| [x, ...rest] =>
+
state.value = rest;
+
state.pull = false;
+
sink(. Push(x));
+
| [] =>
+
state.ended = true;
+
sink(. End);
+
};
+
};
+
state.looping = false;
+
| (Pull, true) => state.pull = true
+
| (Close, _) => state.ended = true
+
},
+
),
+
);
+
});
+16 -13
src/sources/wonka_source_fromValue.re
···
open Wonka_types;
-
let fromValue = x => curry(sink => {
-
let ended = ref(false);
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull when !ended^ => {
-
ended := true;
-
sink(.Push(x));
-
sink(.End);
-
}
-
| _ => ()
-
}
-
}));
-
});
···
open Wonka_types;
+
let fromValue = x =>
+
curry(sink => {
+
let ended = ref(false);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull when ! ended^ =>
+
ended := true;
+
sink(. Push(x));
+
sink(. End);
+
| _ => ()
+
},
+
),
+
);
+
});
+17 -12
src/sources/wonka_source_make.re
···
open Wonka_types;
-
let make = f => curry(sink => {
-
let teardown = ref((.) => ());
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => teardown^(.)
-
| Pull => ()
-
}
-
}));
-
teardown := f(.{
-
next: value => sink(.Push(value)),
-
complete: () => sink(.End)
});
-
});
···
open Wonka_types;
+
let make = f =>
+
curry(sink => {
+
let teardown = ref((.) => ());
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close => teardown^(.)
+
| Pull => ()
+
},
+
),
+
);
+
teardown :=
+
f(. {
+
next: value => sink(. Push(value)),
+
complete: () => sink(. End),
+
});
});
+12 -9
src/sources/wonka_source_makeSubject.re
···
type subjectState('a) = {
mutable sinks: Rebel.Array.t(sinkT('a)),
-
mutable ended: bool
};
let makeSubject = () => {
···
let source = sink => {
state.sinks = Rebel.Array.append(state.sinks, sink);
-
sink(.Start((.signal) => {
-
if (signal === Close) {
-
state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink);
-
}
-
}));
};
let next = value =>
if (!state.ended) {
-
Rebel.Array.forEach(state.sinks, sink => sink(.Push(value)));
};
let complete = () =>
if (!state.ended) {
state.ended = true;
-
Rebel.Array.forEach(state.sinks, sink => sink(.End));
};
-
{ source, next, complete }
};
···
type subjectState('a) = {
mutable sinks: Rebel.Array.t(sinkT('a)),
+
mutable ended: bool,
};
let makeSubject = () => {
···
let source = sink => {
state.sinks = Rebel.Array.append(state.sinks, sink);
+
sink(.
+
Start(
+
(. signal) =>
+
if (signal === Close) {
+
state.sinks = Rebel.Array.filter(state.sinks, x => x !== sink);
+
},
+
),
+
);
};
let next = value =>
if (!state.ended) {
+
Rebel.Array.forEach(state.sinks, sink => sink(. Push(value)));
};
let complete = () =>
if (!state.ended) {
state.ended = true;
+
Rebel.Array.forEach(state.sinks, sink => sink(. End));
};
+
{source, next, complete};
};
+3 -3
src/sources/wonka_source_primitives.re
···
open Wonka_helpers;
let empty = sink => {
-
sink(.Start(talkbackPlaceholder));
-
sink(.End);
};
let never = sink => {
-
sink(.Start(talkbackPlaceholder));
};
···
open Wonka_helpers;
let empty = sink => {
+
sink(. Start(talkbackPlaceholder));
+
sink(. End);
};
let never = sink => {
+
sink(. Start(talkbackPlaceholder));
};
+49 -40
src/web/wonka_operator_debounce.re
···
open Wonka_types;
-
let debounce = f => curry(source => curry(sink => {
-
let gotEndSignal = ref(false);
-
let id: ref(option(Js.Global.timeoutId)) = ref(None);
-
let clearTimeout = () =>
-
switch (id^) {
-
| Some(timeoutId) => {
-
id := None;
-
Js.Global.clearTimeout(timeoutId);
-
}
-
| None => ()
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => {
-
sink(.Start((.signal) => {
switch (signal) {
-
| Close => {
clearTimeout();
-
tb(.Close);
-
}
-
| _ => tb(.signal)
-
}
-
}));
-
}
-
| Push(x) => {
-
clearTimeout();
-
id := Some(Js.Global.setTimeout(() => {
-
id := None;
-
sink(.signal);
-
if (gotEndSignal^) sink(.End);
-
}, f(.x)));
-
}
-
| End => {
-
gotEndSignal := true;
-
switch (id^) {
-
| None => sink(.End)
-
| _ => ()
-
};
-
}
-
}
-
});
-
}));
···
open Wonka_types;
+
let debounce = f =>
+
curry(source =>
+
curry(sink => {
+
let gotEndSignal = ref(false);
+
let id: ref(option(Js.Global.timeoutId)) = ref(None);
+
let clearTimeout = () =>
+
switch (id^) {
+
| Some(timeoutId) =>
+
id := None;
+
Js.Global.clearTimeout(timeoutId);
+
| None => ()
+
};
+
source((. signal) =>
switch (signal) {
+
| Start(tb) =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
clearTimeout();
+
tb(. Close);
+
| _ => tb(. signal)
+
},
+
),
+
)
+
| Push(x) =>
clearTimeout();
+
id :=
+
Some(
+
Js.Global.setTimeout(
+
() => {
+
id := None;
+
sink(. signal);
+
if (gotEndSignal^) {
+
sink(. End);
+
};
+
},
+
f(. x),
+
),
+
);
+
| End =>
+
gotEndSignal := true;
+
switch (id^) {
+
| None => sink(. End)
+
| _ => ()
+
};
+
}
+
);
+
})
+
);
+47 -36
src/web/wonka_operator_delay.re
···
open Wonka_types;
type delayStateT = {
-
mutable talkback: (.talkbackT) => unit,
mutable active: int,
-
mutable gotEndSignal: bool
};
-
let delay = wait => curry(source => curry(sink => {
-
let state: delayStateT = {
-
talkback: Wonka_helpers.talkbackPlaceholder,
-
active: 0,
-
gotEndSignal: false
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => state.talkback = tb
-
| _ when !state.gotEndSignal => {
-
state.active = state.active + 1;
-
ignore(Js.Global.setTimeout(() => {
-
if (state.gotEndSignal && state.active === 0) {
-
sink(.End);
-
} else {
-
state.active = state.active - 1;
-
};
-
sink(.signal);
-
}, wait));
-
}
-
| _ => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => {
-
state.gotEndSignal = true;
-
if (state.active === 0) sink(.End);
-
}
-
| _ when !state.gotEndSignal => state.talkback(.signal)
-
| _ => ()
-
}
-
}));
-
}));
···
open Wonka_types;
type delayStateT = {
+
mutable talkback: (. talkbackT) => unit,
mutable active: int,
+
mutable gotEndSignal: bool,
};
+
let delay = wait =>
+
curry(source =>
+
curry(sink => {
+
let state: delayStateT = {
+
talkback: Wonka_helpers.talkbackPlaceholder,
+
active: 0,
+
gotEndSignal: false,
+
};
+
source((. signal) =>
+
switch (signal) {
+
| Start(tb) => state.talkback = tb
+
| _ when !state.gotEndSignal =>
+
state.active = state.active + 1;
+
ignore(
+
Js.Global.setTimeout(
+
() => {
+
if (state.gotEndSignal && state.active === 0) {
+
sink(. End);
+
} else {
+
state.active = state.active - 1;
+
};
+
sink(. signal);
+
},
+
wait,
+
),
+
);
+
| _ => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
state.gotEndSignal = true;
+
if (state.active === 0) {
+
sink(. End);
+
};
+
| _ when !state.gotEndSignal => state.talkback(. signal)
+
| _ => ()
+
},
+
),
+
);
+
})
+
);
+22 -14
src/web/wonka_operator_interval.re
···
open Wonka_types;
-
let interval = p => curry(sink => {
-
let i = ref(0);
-
let id = Js.Global.setInterval(() => {
-
let num = i^;
-
i := i^ + 1;
-
sink(.Push(num));
-
}, p);
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => Js.Global.clearInterval(id)
-
| _ => ()
-
}
-
}));
-
});
···
open Wonka_types;
+
let interval = p =>
+
curry(sink => {
+
let i = ref(0);
+
let id =
+
Js.Global.setInterval(
+
() => {
+
let num = i^;
+
i := i^ + 1;
+
sink(. Push(num));
+
},
+
p,
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close => Js.Global.clearInterval(id)
+
| _ => ()
+
},
+
),
+
);
+
});
+50 -49
src/web/wonka_operator_sample.re
···
type sampleStateT('a) = {
mutable ended: bool,
mutable value: option('a),
-
mutable sourceTalkback: (.talkbackT) => unit,
-
mutable notifierTalkback: (.talkbackT) => unit
};
-
let sample = notifier => curry(source => curry(sink => {
-
let state = {
-
ended: false,
-
value: None,
-
sourceTalkback: (._: talkbackT) => (),
-
notifierTalkback: (._: talkbackT) => ()
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => state.sourceTalkback = tb
-
| End => {
-
state.ended = true;
-
state.notifierTalkback(.Close);
-
sink(.End);
-
}
-
| Push(x) => state.value = Some(x)
-
}
-
});
-
notifier((.signal) => {
-
switch (signal, state.value) {
-
| (Start(tb), _) => state.notifierTalkback = tb
-
| (End, _) => {
-
state.ended = true;
-
state.sourceTalkback(.Close);
-
sink(.End);
-
}
-
| (Push(_), Some(x)) when !state.ended => {
-
state.value = None;
-
sink(.Push(x));
-
}
-
| (Push(_), _) => ()
-
}
-
});
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Pull => {
-
state.sourceTalkback(.Pull);
-
state.notifierTalkback(.Pull);
-
}
-
| Close => {
-
state.ended = true;
-
state.sourceTalkback(.Close);
-
state.notifierTalkback(.Close);
-
}
-
}
-
}));
-
}));
···
type sampleStateT('a) = {
mutable ended: bool,
mutable value: option('a),
+
mutable sourceTalkback: (. talkbackT) => unit,
+
mutable notifierTalkback: (. talkbackT) => unit,
};
+
let sample = notifier =>
+
curry(source =>
+
curry(sink => {
+
let state = {
+
ended: false,
+
value: None,
+
sourceTalkback: (. _: talkbackT) => (),
+
notifierTalkback: (. _: talkbackT) => (),
+
};
+
source((. signal) =>
+
switch (signal) {
+
| Start(tb) => state.sourceTalkback = tb
+
| End =>
+
state.ended = true;
+
state.notifierTalkback(. Close);
+
sink(. End);
+
| Push(x) => state.value = Some(x)
+
}
+
);
+
notifier((. signal) =>
+
switch (signal, state.value) {
+
| (Start(tb), _) => state.notifierTalkback = tb
+
| (End, _) =>
+
state.ended = true;
+
state.sourceTalkback(. Close);
+
sink(. End);
+
| (Push(_), Some(x)) when !state.ended =>
+
state.value = None;
+
sink(. Push(x));
+
| (Push(_), _) => ()
+
}
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Pull =>
+
state.sourceTalkback(. Pull);
+
state.notifierTalkback(. Pull);
+
| Close =>
+
state.ended = true;
+
state.sourceTalkback(. Close);
+
state.notifierTalkback(. Close);
+
},
+
),
+
);
+
})
+
);
+43 -35
src/web/wonka_operator_throttle.re
···
open Wonka_types;
-
let throttle = f => curry(source => curry(sink => {
-
let skip = ref(false);
-
let id: ref(option(Js.Global.timeoutId)) = ref(None);
-
let clearTimeout = () =>
-
switch (id^) {
-
| Some(timeoutId) => Js.Global.clearTimeout(timeoutId);
-
| None => ()
-
};
-
source((.signal) => {
-
switch (signal) {
-
| Start(tb) => {
-
sink(.Start((.signal) => {
switch (signal) {
-
| Close => {
clearTimeout();
-
tb(.Close);
-
}
-
| _ => tb(.signal)
}
-
}));
-
}
-
| End => {
-
clearTimeout();
-
sink(.End);
-
}
-
| Push(x) when !skip^ => {
-
skip := true;
-
clearTimeout();
-
id := Some(Js.Global.setTimeout(() => {
-
id := None;
-
skip := false;
-
}, f(.x)));
-
sink(.signal);
-
}
-
| Push(_) => ()
-
}
-
});
-
}));
···
open Wonka_types;
+
let throttle = f =>
+
curry(source =>
+
curry(sink => {
+
let skip = ref(false);
+
let id: ref(option(Js.Global.timeoutId)) = ref(None);
+
let clearTimeout = () =>
+
switch (id^) {
+
| Some(timeoutId) => Js.Global.clearTimeout(timeoutId)
+
| None => ()
+
};
+
source((. signal) =>
switch (signal) {
+
| Start(tb) =>
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close =>
+
clearTimeout();
+
tb(. Close);
+
| _ => tb(. signal)
+
},
+
),
+
)
+
| End =>
clearTimeout();
+
sink(. End);
+
| Push(x) when ! skip^ =>
+
skip := true;
+
clearTimeout();
+
id :=
+
Some(
+
Js.Global.setTimeout(
+
() => {
+
id := None;
+
skip := false;
+
},
+
f(. x),
+
),
+
);
+
sink(. signal);
+
| Push(_) => ()
}
+
);
+
})
+
);
+11 -11
src/web/wonka_sink_toPromise.re
···
open Wonka_types;
let toPromise = source => {
-
open Wonka_operator_takeLast;
-
-
Js.Promise.make((~resolve, ~reject as _) => {
-
takeLast(1, source, (.signal) => {
-
switch (signal) {
-
| Start(x) => x(.Pull)
-
| Push(x) => resolve(.x)
-
| End => ()
-
}
-
});
-
});
};
···
open Wonka_types;
let toPromise = source => {
+
Wonka_operator_takeLast.(
+
Js.Promise.make((~resolve, ~reject as _) =>
+
takeLast(1, source, (. signal) =>
+
switch (signal) {
+
| Start(x) => x(. Pull)
+
| Push(x) => resolve(. x)
+
| End => ()
+
}
+
)
+
)
+
);
};
+16 -19
src/web/wonka_source_fromDomEvent.re
···
open Wonka_types;
open Wonka_source_fromListener;
-
let fromDomEvent = (element, event) => curry(sink => {
-
let addEventListener: (
-
Dom.element,
-
string,
-
(Dom.event) => unit
-
) => unit = [%raw {|
function (element, event, handler) {
element.addEventListener(event, handler);
}
-
|}];
-
let removeEventListener: (
-
Dom.element,
-
string,
-
(Dom.event) => unit
-
) => unit = [%raw {|
function (element, event, handler) {
element.removeEventListener(event, handler);
}
-
|}];
-
fromListener(
-
handler => addEventListener(element, event, handler),
-
handler => removeEventListener(element, event, handler),
-
sink
-
)
-
});
···
open Wonka_types;
open Wonka_source_fromListener;
+
let fromDomEvent = (element, event) =>
+
curry(sink => {
+
let addEventListener: (Dom.element, string, Dom.event => unit) => unit = [%raw
+
{|
function (element, event, handler) {
element.addEventListener(event, handler);
}
+
|}
+
];
+
let removeEventListener: (Dom.element, string, Dom.event => unit) => unit = [%raw
+
{|
function (element, event, handler) {
element.removeEventListener(event, handler);
}
+
|}
+
];
+
fromListener(
+
handler => addEventListener(element, event, handler),
+
handler => removeEventListener(element, event, handler),
+
sink,
+
);
+
});
+14 -10
src/web/wonka_source_fromListener.re
···
open Wonka_types;
-
let fromListener = (addListener, removeListener) => curry(sink => {
-
let handler = event => sink(.Push(event));
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => removeListener(handler)
-
| _ => ()
-
}
-
}));
-
addListener(handler);
-
});
···
open Wonka_types;
+
let fromListener = (addListener, removeListener) =>
+
curry(sink => {
+
let handler = event => sink(. Push(event));
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close => removeListener(handler)
+
| _ => ()
+
},
+
),
+
);
+
addListener(handler);
+
});
+25 -16
src/web/wonka_source_fromPromise.re
···
open Wonka_types;
-
let fromPromise = promise => curry(sink => {
-
let ended = ref(false);
-
ignore(Js.Promise.then_(value => {
-
if (!ended^) {
-
sink(.Push(value));
-
sink(.End);
-
};
-
Js.Promise.resolve(())
-
}, promise));
-
sink(.Start((.signal) => {
-
switch (signal) {
-
| Close => ended := true
-
| _ => ()
-
}
-
}));
-
});
···
open Wonka_types;
+
let fromPromise = promise =>
+
curry(sink => {
+
let ended = ref(false);
+
ignore(
+
Js.Promise.then_(
+
value => {
+
if (! ended^) {
+
sink(. Push(value));
+
sink(. End);
+
};
+
Js.Promise.resolve();
+
},
+
promise,
+
),
+
);
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal) {
+
| Close => ended := true
+
| _ => ()
+
},
+
),
+
);
+
});
+31 -26
src/wonka_helpers.re
···
open Wonka_types;
-
let talkbackPlaceholder = (._: talkbackT) => ();
-
let captureTalkback = (
-
source: sourceT('a),
-
sinkWithTalkback: (.signalT('a), (.talkbackT) => unit) => unit
-
) => {
let talkback = ref(talkbackPlaceholder);
-
source((.signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ()
};
-
sinkWithTalkback(.signal, talkback^)
});
};
type trampolineT = {
mutable exhausted: bool,
mutable inLoop: bool,
-
mutable gotSignal: bool
};
-
let makeTrampoline = (sink: sinkT('a), f: (.unit) => option('a)) => {
let state: trampolineT = {
exhausted: false,
inLoop: false,
-
gotSignal: false
};
let loop = () => {
let rec explode = () =>
switch (f(.)) {
-
| Some(x) => {
state.gotSignal = false;
-
sink(.Push(x));
-
if (state.gotSignal) explode();
-
}
-
| None => {
state.exhausted = true;
-
sink(.End)
-
}
};
state.inLoop = true;
···
state.inLoop = false;
};
-
sink(.Start((.signal) => {
-
switch (signal, state.exhausted) {
-
| (Pull, false) => {
-
state.gotSignal = true;
-
if (!state.inLoop) loop();
-
}
-
| _ => ()
-
}
-
}));
};
···
open Wonka_types;
+
let talkbackPlaceholder = (. _: talkbackT) => ();
+
let captureTalkback =
+
(
+
source: sourceT('a),
+
sinkWithTalkback: (. signalT('a), (. talkbackT) => unit) => unit,
+
) => {
let talkback = ref(talkbackPlaceholder);
+
source((. signal) => {
switch (signal) {
| Start(x) => talkback := x
| _ => ()
};
+
sinkWithTalkback(. signal, talkback^);
});
};
type trampolineT = {
mutable exhausted: bool,
mutable inLoop: bool,
+
mutable gotSignal: bool,
};
+
let makeTrampoline = (sink: sinkT('a), f: (. unit) => option('a)) => {
let state: trampolineT = {
exhausted: false,
inLoop: false,
+
gotSignal: false,
};
let loop = () => {
let rec explode = () =>
switch (f(.)) {
+
| Some(x) =>
state.gotSignal = false;
+
sink(. Push(x));
+
if (state.gotSignal) {
+
explode();
+
};
+
| None =>
state.exhausted = true;
+
sink(. End);
};
state.inLoop = true;
···
state.inLoop = false;
};
+
sink(.
+
Start(
+
(. signal) =>
+
switch (signal, state.exhausted) {
+
| (Pull, false) =>
+
state.gotSignal = true;
+
if (!state.inLoop) {
+
loop();
+
};
+
| _ => ()
+
},
+
),
+
);
};
+6 -8
src/wonka_types.re
···
| Close;
type signalT('a) =
-
| Start((.talkbackT) => unit)
| Push('a)
| End;
-
type sinkT('a) = (.signalT('a)) => unit;
type sourceT('a) = sinkT('a) => unit;
-
type teardownT = (.unit) => unit;
-
type subscriptionT = {
-
unsubscribe: unit => unit
-
};
type observerT('a) = {
next: 'a => unit,
-
complete: unit => unit
};
type subjectT('a) = {
source: sourceT('a),
next: 'a => unit,
-
complete: unit => unit
};
/* Sinks and sources need to explicitly be their own callbacks;
···
| Close;
type signalT('a) =
+
| Start((. talkbackT) => unit)
| Push('a)
| End;
+
type sinkT('a) = (. signalT('a)) => unit;
type sourceT('a) = sinkT('a) => unit;
+
type teardownT = (. unit) => unit;
+
type subscriptionT = {unsubscribe: unit => unit};
type observerT('a) = {
next: 'a => unit,
+
complete: unit => unit,
};
type subjectT('a) = {
source: sourceT('a),
next: 'a => unit,
+
complete: unit => unit,
};
/* Sinks and sources need to explicitly be their own callbacks;
+563 -10
yarn.lock
···
core-js "^2.5.7"
regenerator-runtime "^0.12.0"
"@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
···
integrity sha512-TJLx1ti1Cp7e53bCndV7DpMAcZL9+pqA4L9YD4kCrDQuYdA8boRnPh1l862w8AJHWTxEki/xtDu0FVPCq2HVrA==
dependencies:
jest "^23.5.0"
"@types/estree@0.0.39":
version "0.0.39"
···
dependencies:
color-convert "^1.9.0"
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
···
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=
array-unique@^0.2.1:
version "0.2.1"
···
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
···
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
clap@^1.0.9:
version "1.2.3"
resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51"
···
define-property "^0.2.5"
isobject "^3.0.0"
static-extend "^0.1.1"
cliui@^4.0.0:
version "4.1.0"
···
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
···
js-yaml "^3.9.0"
parse-json "^4.0.0"
coveralls@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f"
···
shebang-command "^1.2.0"
which "^1.2.9"
-
cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
···
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
···
dependencies:
ms "^2.1.1"
-
debug@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
···
dependencies:
mimic-response "^1.0.0"
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
···
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
···
version "1.3.102"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.102.tgz#3ac43a037c8a63bca3dfa189eb3d90f097196787"
integrity sha512-2nzZuXw/KBPnI3QX3UOCSRvJiVy7o9+VHRDQ3D/EHCvVc89X6aj/GlNmEgiR2GBIhmSWXIi4W1M5okA5ScSlNg==
emojis-list@^2.0.0:
version "2.1.0"
···
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.1.tgz#6edaa45f3bd570ffe08febce66f7116be4b1cdb6"
integrity sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw==
-
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
···
signal-exit "^3.0.0"
strip-eof "^1.0.0"
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
···
dependencies:
bser "^2.0.0"
-
figures@^1.0.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
dependencies:
escape-string-regexp "^1.0.5"
object-assign "^4.1.0"
filename-regex@^2.0.0:
version "2.0.1"
···
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
···
dependencies:
locate-path "^2.0.0"
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
···
dependencies:
babylon "^6.15.0"
vlq "^0.2.1"
follow-redirects@1.0.0:
version "1.0.0"
···
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
···
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
···
version "0.1.0"
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
globrex@^0.1.1:
version "0.1.2"
···
jsprim "^1.2.2"
sshpk "^1.7.0"
iconv-lite@0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
···
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
indexes-of@^1.0.1:
version "1.0.1"
···
dependencies:
ci-info "^1.5.0"
is-color-stop@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
···
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
is-finite@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
···
dependencies:
is-extglob "^1.0.0"
is-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
···
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
-
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
···
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
is-resolvable@^1.0.0:
version "1.1.0"
···
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
···
prelude-ls "~1.1.2"
type-check "~0.3.2"
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
···
p-locate "^2.0.0"
path-exists "^3.0.0"
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
···
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
···
resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
loose-envify@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
···
integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
dependencies:
object-visit "^1.0.0"
math-expression-evaluator@^1.2.14:
version "1.2.17"
···
parse-glob "^3.0.4"
regex-cache "^0.4.2"
-
micromatch@^3.1.4:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
···
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-run-all@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
···
dependencies:
path-key "^2.0.0"
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
···
dependencies:
wrappy "1"
optimist@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
···
dependencies:
p-try "^1.0.0"
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
···
dependencies:
p-limit "^1.1.0"
p-queue@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34"
···
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
parse-glob@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
···
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
···
integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
dependencies:
find-up "^2.1.0"
pn@^1.1.0:
version "1.1.0"
···
kleur "^2.0.1"
sisteransi "^0.1.1"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
···
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
···
normalize-package-data "^2.3.2"
path-type "^3.0.0"
readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
···
dependencies:
path-parse "^1.0.6"
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
···
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
-
rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
···
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
sade@^1.4.0:
version "1.4.2"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.4.2.tgz#b1946ef9ec62450b74e17d9fec30156c94f193a6"
···
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0:
version "5.6.0"
···
once "^1.3.1"
simple-concat "^1.0.0"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
···
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
snapdragon-node@^2.0.1:
version "2.1.1"
···
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
···
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
string-hash@^1.1.1:
version "1.1.3"
···
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
···
unquote "~1.1.1"
util.promisify "~1.0.0"
symbol-tree@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
tar-fs@^1.13.0:
version "1.16.3"
···
extend-shallow "^3.0.2"
regex-not "^1.0.2"
safe-regex "^1.1.0"
tough-cookie@>=2.3.3:
version "3.0.0"
···
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
-
which@1, which@^1.2.12, which@^1.2.9, which@^1.3.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
···
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrappy@1:
version "1.0.2"
···
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^9.0.2"
···
core-js "^2.5.7"
regenerator-runtime "^0.12.0"
+
"@babel/runtime@7.0.0":
+
version "7.0.0"
+
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c"
+
integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==
+
dependencies:
+
regenerator-runtime "^0.12.0"
+
"@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
···
integrity sha512-TJLx1ti1Cp7e53bCndV7DpMAcZL9+pqA4L9YD4kCrDQuYdA8boRnPh1l862w8AJHWTxEki/xtDu0FVPCq2HVrA==
dependencies:
jest "^23.5.0"
+
+
"@samverschueren/stream-to-observable@^0.3.0":
+
version "0.3.0"
+
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
+
integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==
+
dependencies:
+
any-observable "^0.3.0"
"@types/estree@0.0.39":
version "0.0.39"
···
dependencies:
color-convert "^1.9.0"
+
any-observable@^0.3.0:
+
version "0.3.0"
+
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
+
integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
+
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
···
version "0.0.0"
resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b"
integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=
+
+
array-union@^1.0.1:
+
version "1.0.2"
+
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+
integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
+
dependencies:
+
array-uniq "^1.0.1"
+
+
array-uniq@^1.0.1:
+
version "1.0.3"
+
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+
integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
array-unique@^0.2.1:
version "0.2.1"
···
strip-ansi "^3.0.0"
supports-color "^2.0.0"
+
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1, chalk@^2.4.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
···
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
ci-info@^2.0.0:
+
version "2.0.0"
+
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
clap@^1.0.9:
version "1.2.3"
resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51"
···
define-property "^0.2.5"
isobject "^3.0.0"
static-extend "^0.1.1"
+
+
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
+
version "2.1.0"
+
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+
integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+
dependencies:
+
restore-cursor "^2.0.0"
+
+
cli-truncate@^0.2.1:
+
version "0.2.1"
+
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
+
integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=
+
dependencies:
+
slice-ansi "0.0.4"
+
string-width "^1.0.1"
cliui@^4.0.0:
version "4.1.0"
···
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
+
commander@^2.14.1, commander@^2.9.0:
+
version "2.20.0"
+
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
+
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
+
commander@~2.17.1:
version "2.17.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
···
js-yaml "^3.9.0"
parse-json "^4.0.0"
+
cosmiconfig@^5.0.2, cosmiconfig@^5.0.7:
+
version "5.2.0"
+
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.0.tgz#45038e4d28a7fe787203aede9c25bca4a08b12c8"
+
integrity sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==
+
dependencies:
+
import-fresh "^2.0.0"
+
is-directory "^0.3.1"
+
js-yaml "^3.13.0"
+
parse-json "^4.0.0"
+
coveralls@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f"
···
shebang-command "^1.2.0"
which "^1.2.9"
+
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
···
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
+
date-fns@^1.27.2:
+
version "1.30.1"
+
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c"
+
integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==
+
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
···
dependencies:
ms "^2.1.1"
+
debug@^4.0.1, debug@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
···
dependencies:
mimic-response "^1.0.0"
+
dedent@^0.7.0:
+
version "0.7.0"
+
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
+
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
···
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
+
del@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+
integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=
+
dependencies:
+
globby "^6.1.0"
+
is-path-cwd "^1.0.0"
+
is-path-in-cwd "^1.0.0"
+
p-map "^1.1.1"
+
pify "^3.0.0"
+
rimraf "^2.2.8"
+
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
···
version "1.3.102"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.102.tgz#3ac43a037c8a63bca3dfa189eb3d90f097196787"
integrity sha512-2nzZuXw/KBPnI3QX3UOCSRvJiVy7o9+VHRDQ3D/EHCvVc89X6aj/GlNmEgiR2GBIhmSWXIi4W1M5okA5ScSlNg==
+
+
elegant-spinner@^1.0.1:
+
version "1.0.1"
+
resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
+
integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=
emojis-list@^2.0.0:
version "2.1.0"
···
resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.0.1.tgz#6edaa45f3bd570ffe08febce66f7116be4b1cdb6"
integrity sha512-J3ZkwbEnnO+fGAKrjVpeUAnZshAdfZvbhQpqfIH9kSAspReRC4nJnu8ewm55b4y9ElyeuhCTzJD0XiH8Tsbhlw==
+
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
···
signal-exit "^3.0.0"
strip-eof "^1.0.0"
+
execa@^1.0.0:
+
version "1.0.0"
+
resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+
integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
+
dependencies:
+
cross-spawn "^6.0.0"
+
get-stream "^4.0.0"
+
is-stream "^1.1.0"
+
npm-run-path "^2.0.0"
+
p-finally "^1.0.0"
+
signal-exit "^3.0.0"
+
strip-eof "^1.0.0"
+
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
···
dependencies:
bser "^2.0.0"
+
figures@^1.0.1, figures@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=
dependencies:
escape-string-regexp "^1.0.5"
object-assign "^4.1.0"
+
+
figures@^2.0.0:
+
version "2.0.0"
+
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+
integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+
dependencies:
+
escape-string-regexp "^1.0.5"
filename-regex@^2.0.0:
version "2.0.1"
···
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
+
find-parent-dir@^0.3.0:
+
version "0.3.0"
+
resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54"
+
integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=
+
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
···
dependencies:
locate-path "^2.0.0"
+
find-up@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+
integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+
dependencies:
+
locate-path "^3.0.0"
+
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
···
dependencies:
babylon "^6.15.0"
vlq "^0.2.1"
+
+
fn-name@~2.0.1:
+
version "2.0.1"
+
resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7"
+
integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=
follow-redirects@1.0.0:
version "1.0.0"
···
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
g-status@^2.0.2:
+
version "2.0.2"
+
resolved "https://registry.yarnpkg.com/g-status/-/g-status-2.0.2.tgz#270fd32119e8fc9496f066fe5fe88e0a6bc78b97"
+
integrity sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==
+
dependencies:
+
arrify "^1.0.1"
+
matcher "^1.0.0"
+
simple-git "^1.85.0"
+
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
···
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+
get-own-enumerable-property-symbols@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203"
+
integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==
+
+
get-stdin@^6.0.0:
+
version "6.0.0"
+
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
+
integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
+
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+
+
get-stream@^4.0.0:
+
version "4.1.0"
+
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+
dependencies:
+
pump "^3.0.0"
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
···
version "0.1.0"
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
+
+
globby@^6.1.0:
+
version "6.1.0"
+
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+
integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
+
dependencies:
+
array-union "^1.0.1"
+
glob "^7.0.3"
+
object-assign "^4.0.1"
+
pify "^2.0.0"
+
pinkie-promise "^2.0.0"
globrex@^0.1.1:
version "0.1.2"
···
jsprim "^1.2.2"
sshpk "^1.7.0"
+
husky@^1.3.1:
+
version "1.3.1"
+
resolved "https://registry.yarnpkg.com/husky/-/husky-1.3.1.tgz#26823e399300388ca2afff11cfa8a86b0033fae0"
+
integrity sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==
+
dependencies:
+
cosmiconfig "^5.0.7"
+
execa "^1.0.0"
+
find-up "^3.0.0"
+
get-stdin "^6.0.0"
+
is-ci "^2.0.0"
+
pkg-dir "^3.0.0"
+
please-upgrade-node "^3.1.1"
+
read-pkg "^4.0.1"
+
run-node "^1.0.0"
+
slash "^2.0.0"
+
iconv-lite@0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
···
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+
+
indent-string@^3.0.0:
+
version "3.2.0"
+
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
+
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
indexes-of@^1.0.1:
version "1.0.1"
···
dependencies:
ci-info "^1.5.0"
+
is-ci@^2.0.0:
+
version "2.0.0"
+
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+
integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+
dependencies:
+
ci-info "^2.0.0"
+
is-color-stop@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
···
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
+
is-extglob@^2.1.1:
+
version "2.1.1"
+
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
+
is-finite@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
···
dependencies:
is-extglob "^1.0.0"
+
is-glob@^4.0.0:
+
version "4.0.1"
+
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
+
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
+
dependencies:
+
is-extglob "^2.1.1"
+
is-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
···
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
+
is-obj@^1.0.0, is-obj@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
+
is-observable@^1.1.0:
+
version "1.1.0"
+
resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e"
+
integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==
+
dependencies:
+
symbol-observable "^1.1.0"
+
+
is-path-cwd@^1.0.0:
+
version "1.0.0"
+
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+
integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
+
+
is-path-in-cwd@^1.0.0:
+
version "1.0.1"
+
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52"
+
integrity sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==
+
dependencies:
+
is-path-inside "^1.0.0"
+
+
is-path-inside@^1.0.0:
+
version "1.0.1"
+
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+
integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
+
dependencies:
+
path-is-inside "^1.0.1"
+
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
···
resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
+
is-promise@^2.1.0:
+
version "2.1.0"
+
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+
integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
+
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
+
+
is-regexp@^1.0.0:
+
version "1.0.0"
+
resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+
integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
is-resolvable@^1.0.0:
version "1.1.0"
···
argparse "^1.0.7"
esprima "^4.0.0"
+
js-yaml@^3.13.0:
+
version "3.13.1"
+
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
+
dependencies:
+
argparse "^1.0.7"
+
esprima "^4.0.0"
+
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
···
prelude-ls "~1.1.2"
type-check "~0.3.2"
+
lint-staged@^8.1.5:
+
version "8.1.5"
+
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.1.5.tgz#372476fe1a58b8834eb562ed4c99126bd60bdd79"
+
integrity sha512-e5ZavfnSLcBJE1BTzRTqw6ly8OkqVyO3GL2M6teSmTBYQ/2BuueD5GIt2RPsP31u/vjKdexUyDCxSyK75q4BDA==
+
dependencies:
+
chalk "^2.3.1"
+
commander "^2.14.1"
+
cosmiconfig "^5.0.2"
+
debug "^3.1.0"
+
dedent "^0.7.0"
+
del "^3.0.0"
+
execa "^1.0.0"
+
find-parent-dir "^0.3.0"
+
g-status "^2.0.2"
+
is-glob "^4.0.0"
+
is-windows "^1.0.2"
+
listr "^0.14.2"
+
listr-update-renderer "^0.5.0"
+
lodash "^4.17.11"
+
log-symbols "^2.2.0"
+
micromatch "^3.1.8"
+
npm-which "^3.0.1"
+
p-map "^1.1.1"
+
path-is-inside "^1.0.2"
+
pify "^3.0.0"
+
please-upgrade-node "^3.0.2"
+
staged-git-files "1.1.2"
+
string-argv "^0.0.2"
+
stringify-object "^3.2.2"
+
yup "^0.26.10"
+
+
listr-silent-renderer@^1.1.1:
+
version "1.1.1"
+
resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e"
+
integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=
+
+
listr-update-renderer@^0.5.0:
+
version "0.5.0"
+
resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2"
+
integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==
+
dependencies:
+
chalk "^1.1.3"
+
cli-truncate "^0.2.1"
+
elegant-spinner "^1.0.1"
+
figures "^1.7.0"
+
indent-string "^3.0.0"
+
log-symbols "^1.0.2"
+
log-update "^2.3.0"
+
strip-ansi "^3.0.1"
+
+
listr-verbose-renderer@^0.5.0:
+
version "0.5.0"
+
resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db"
+
integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==
+
dependencies:
+
chalk "^2.4.1"
+
cli-cursor "^2.1.0"
+
date-fns "^1.27.2"
+
figures "^2.0.0"
+
+
listr@^0.14.2:
+
version "0.14.3"
+
resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586"
+
integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==
+
dependencies:
+
"@samverschueren/stream-to-observable" "^0.3.0"
+
is-observable "^1.1.0"
+
is-promise "^2.1.0"
+
is-stream "^1.1.0"
+
listr-silent-renderer "^1.1.1"
+
listr-update-renderer "^0.5.0"
+
listr-verbose-renderer "^0.5.0"
+
p-map "^2.0.0"
+
rxjs "^6.3.3"
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
···
p-locate "^2.0.0"
path-exists "^3.0.0"
+
locate-path@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+
integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+
dependencies:
+
p-locate "^3.0.0"
+
path-exists "^3.0.0"
+
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
···
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
+
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4:
version "4.17.11"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
···
resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
+
log-symbols@^1.0.2:
+
version "1.0.2"
+
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
+
integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=
+
dependencies:
+
chalk "^1.0.0"
+
+
log-symbols@^2.2.0:
+
version "2.2.0"
+
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
+
integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
+
dependencies:
+
chalk "^2.0.1"
+
+
log-update@^2.3.0:
+
version "2.3.0"
+
resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708"
+
integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg=
+
dependencies:
+
ansi-escapes "^3.0.0"
+
cli-cursor "^2.0.0"
+
wrap-ansi "^3.0.1"
+
loose-envify@^1.0.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
···
integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
dependencies:
object-visit "^1.0.0"
+
+
matcher@^1.0.0:
+
version "1.1.1"
+
resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2"
+
integrity sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==
+
dependencies:
+
escape-string-regexp "^1.0.4"
math-expression-evaluator@^1.2.14:
version "1.2.17"
···
parse-glob "^3.0.4"
regex-cache "^0.4.2"
+
micromatch@^3.1.4, micromatch@^3.1.8:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
···
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
+
npm-path@^2.0.2:
+
version "2.0.4"
+
resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64"
+
integrity sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==
+
dependencies:
+
which "^1.2.10"
+
npm-run-all@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
···
dependencies:
path-key "^2.0.0"
+
npm-which@^3.0.1:
+
version "3.0.1"
+
resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa"
+
integrity sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=
+
dependencies:
+
commander "^2.9.0"
+
npm-path "^2.0.2"
+
which "^1.2.10"
+
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.1, npmlog@^4.0.2, npmlog@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
···
dependencies:
wrappy "1"
+
onetime@^2.0.0:
+
version "2.0.1"
+
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+
integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
+
dependencies:
+
mimic-fn "^1.0.0"
+
optimist@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
···
dependencies:
p-try "^1.0.0"
+
p-limit@^2.0.0:
+
version "2.2.0"
+
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2"
+
integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==
+
dependencies:
+
p-try "^2.0.0"
+
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
···
dependencies:
p-limit "^1.1.0"
+
p-locate@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+
integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+
dependencies:
+
p-limit "^2.0.0"
+
+
p-map@^1.1.1:
+
version "1.2.0"
+
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b"
+
integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==
+
+
p-map@^2.0.0:
+
version "2.1.0"
+
resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175"
+
integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==
+
p-queue@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-2.4.2.tgz#03609826682b743be9a22dba25051bd46724fc34"
···
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
+
p-try@^2.0.0:
+
version "2.2.0"
+
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
parse-glob@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
···
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
+
version "1.0.2"
+
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+
integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
···
integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
dependencies:
find-up "^2.1.0"
+
+
pkg-dir@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+
integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+
dependencies:
+
find-up "^3.0.0"
+
+
please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1:
+
version "3.1.1"
+
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
+
integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==
+
dependencies:
+
semver-compare "^1.0.0"
pn@^1.1.0:
version "1.1.0"
···
kleur "^2.0.1"
sisteransi "^0.1.1"
+
property-expr@^1.5.0:
+
version "1.5.1"
+
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f"
+
integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==
+
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
···
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
+
dependencies:
+
end-of-stream "^1.1.0"
+
once "^1.3.1"
+
+
pump@^3.0.0:
+
version "3.0.0"
+
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
···
normalize-package-data "^2.3.2"
path-type "^3.0.0"
+
read-pkg@^4.0.1:
+
version "4.0.1"
+
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
+
integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
+
dependencies:
+
normalize-package-data "^2.3.2"
+
parse-json "^4.0.0"
+
pify "^3.0.0"
+
readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
···
dependencies:
path-parse "^1.0.6"
+
restore-cursor@^2.0.0:
+
version "2.0.0"
+
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+
integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
+
dependencies:
+
onetime "^2.0.0"
+
signal-exit "^3.0.2"
+
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
···
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
+
rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
version "2.6.3"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
···
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==
+
run-node@^1.0.0:
+
version "1.0.0"
+
resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
+
integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==
+
+
rxjs@^6.3.3:
+
version "6.4.0"
+
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504"
+
integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==
+
dependencies:
+
tslib "^1.9.0"
+
sade@^1.4.0:
version "1.4.2"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.4.2.tgz#b1946ef9ec62450b74e17d9fec30156c94f193a6"
···
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+
semver-compare@^1.0.0:
+
version "1.0.0"
+
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
+
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0:
version "5.6.0"
···
once "^1.3.1"
simple-concat "^1.0.0"
+
simple-git@^1.85.0:
+
version "1.110.0"
+
resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.110.0.tgz#54eb179089d055a7783d32399246cebc9d9933e9"
+
integrity sha512-UYY0rQkknk0P5eb+KW+03F4TevZ9ou0H+LoGaj7iiVgpnZH4wdj/HTViy/1tNNkmIPcmtxuBqXWiYt2YwlRKOQ==
+
dependencies:
+
debug "^4.0.1"
+
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
···
version "1.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
+
+
slash@^2.0.0:
+
version "2.0.0"
+
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
+
slice-ansi@0.0.4:
+
version "0.0.4"
+
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
+
integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=
snapdragon-node@^2.0.1:
version "2.1.1"
···
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
+
staged-git-files@1.1.2:
+
version "1.1.2"
+
resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b"
+
integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==
+
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
···
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
+
+
string-argv@^0.0.2:
+
version "0.0.2"
+
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736"
+
integrity sha1-2sMECGkMIfPDYwo/86BYd73L1zY=
string-hash@^1.1.1:
version "1.1.3"
···
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
+
+
stringify-object@^3.2.2:
+
version "3.3.0"
+
resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
+
integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
+
dependencies:
+
get-own-enumerable-property-symbols "^3.0.0"
+
is-obj "^1.0.1"
+
is-regexp "^1.0.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
···
unquote "~1.1.1"
util.promisify "~1.0.0"
+
symbol-observable@^1.1.0:
+
version "1.2.0"
+
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
+
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
+
symbol-tree@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=
+
+
synchronous-promise@^2.0.5:
+
version "2.0.7"
+
resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.7.tgz#3574b3d2fae86b145356a4b89103e1577f646fe3"
+
integrity sha512-16GbgwTmFMYFyQMLvtQjvNWh30dsFe1cAW5Fg1wm5+dg84L9Pe36mftsIRU95/W2YsISxsz/xq4VB23sqpgb/A==
tar-fs@^1.13.0:
version "1.16.3"
···
extend-shallow "^3.0.2"
regex-not "^1.0.2"
safe-regex "^1.1.0"
+
+
toposort@^2.0.2:
+
version "2.0.2"
+
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
+
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
tough-cookie@>=2.3.3:
version "3.0.0"
···
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
+
which@1, which@^1.2.10, which@^1.2.12, which@^1.2.9, which@^1.3.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
···
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
+
+
wrap-ansi@^3.0.1:
+
version "3.0.1"
+
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
+
integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=
+
dependencies:
+
string-width "^2.1.1"
+
strip-ansi "^4.0.0"
wrappy@1:
version "1.0.2"
···
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^9.0.2"
+
+
yup@^0.26.10:
+
version "0.26.10"
+
resolved "https://registry.yarnpkg.com/yup/-/yup-0.26.10.tgz#3545839663289038faf25facfc07e11fd67c0cb1"
+
integrity sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw==
+
dependencies:
+
"@babel/runtime" "7.0.0"
+
fn-name "~2.0.1"
+
lodash "^4.17.10"
+
property-expr "^1.5.0"
+
synchronous-promise "^2.0.5"
+
toposort "^2.0.2"