@fncts/observable 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Action.d.ts +6 -0
- package/AnimationFrameAction.d.ts +11 -0
- package/AnimationFrameScheduler.d.ts +6 -0
- package/AsyncAction.d.ts +19 -0
- package/AsyncScheduler.d.ts +11 -0
- package/BehaviorSubject.d.ts +10 -0
- package/Notification.d.ts +59 -0
- package/Observable/api/connect.d.ts +10 -0
- package/Observable/api/connectable.d.ts +24 -0
- package/Observable/api/fromCallback.d.ts +11 -0
- package/Observable/api/fromEvent.d.ts +4 -0
- package/Observable/api/index.d.ts +14 -0
- package/Observable/api/race.d.ts +9 -0
- package/Observable/api/raceWith.d.ts +6 -0
- package/Observable/api/repeatWhen.d.ts +5 -0
- package/Observable/api/retryWhen.d.ts +10 -0
- package/Observable/api/share.d.ts +16 -0
- package/Observable/api/window.d.ts +8 -0
- package/Observable/api/windowCount.d.ts +6 -0
- package/Observable/api/windowTime.d.ts +12 -0
- package/Observable/api/windowToggle.d.ts +8 -0
- package/Observable/api/windowWhen.d.ts +9 -0
- package/Observable/api.d.ts +668 -0
- package/Observable/definition.d.ts +32 -0
- package/Observable/dom/animationFrames.d.ts +6 -0
- package/Observable/instances.d.ts +1 -0
- package/Observable.d.ts +19 -0
- package/Observer.d.ts +6 -0
- package/Operator.d.ts +19 -0
- package/Scheduler.d.ts +22 -0
- package/Subject.d.ts +48 -0
- package/Subscriber.d.ts +27 -0
- package/Subscription.d.ts +41 -0
- package/_cjs/Action.cjs +27 -0
- package/_cjs/Action.cjs.map +1 -0
- package/_cjs/AnimationFrameAction.cjs +48 -0
- package/_cjs/AnimationFrameAction.cjs.map +1 -0
- package/_cjs/AnimationFrameScheduler.cjs +51 -0
- package/_cjs/AnimationFrameScheduler.cjs.map +1 -0
- package/_cjs/AsyncAction.cjs +116 -0
- package/_cjs/AsyncAction.cjs.map +1 -0
- package/_cjs/AsyncScheduler.cjs +61 -0
- package/_cjs/AsyncScheduler.cjs.map +1 -0
- package/_cjs/BehaviorSubject.cjs +52 -0
- package/_cjs/BehaviorSubject.cjs.map +1 -0
- package/_cjs/Notification.cjs +110 -0
- package/_cjs/Notification.cjs.map +1 -0
- package/_cjs/Observable/api/connect.cjs +35 -0
- package/_cjs/Observable/api/connect.cjs.map +1 -0
- package/_cjs/Observable/api/connectable.cjs +64 -0
- package/_cjs/Observable/api/connectable.cjs.map +1 -0
- package/_cjs/Observable/api/fromCallback.cjs +74 -0
- package/_cjs/Observable/api/fromCallback.cjs.map +1 -0
- package/_cjs/Observable/api/fromEvent.cjs +22 -0
- package/_cjs/Observable/api/fromEvent.cjs.map +1 -0
- package/_cjs/Observable/api/index.cjs +188 -0
- package/_cjs/Observable/api/index.cjs.map +1 -0
- package/_cjs/Observable/api/race.cjs +47 -0
- package/_cjs/Observable/api/race.cjs.map +1 -0
- package/_cjs/Observable/api/raceWith.cjs +24 -0
- package/_cjs/Observable/api/raceWith.cjs.map +1 -0
- package/_cjs/Observable/api/repeatWhen.cjs +72 -0
- package/_cjs/Observable/api/repeatWhen.cjs.map +1 -0
- package/_cjs/Observable/api/retryWhen.cjs +61 -0
- package/_cjs/Observable/api/retryWhen.cjs.map +1 -0
- package/_cjs/Observable/api/share.cjs +115 -0
- package/_cjs/Observable/api/share.cjs.map +1 -0
- package/_cjs/Observable/api/window.cjs +53 -0
- package/_cjs/Observable/api/window.cjs.map +1 -0
- package/_cjs/Observable/api/windowCount.cjs +62 -0
- package/_cjs/Observable/api/windowCount.cjs.map +1 -0
- package/_cjs/Observable/api/windowTime.cjs +90 -0
- package/_cjs/Observable/api/windowTime.cjs.map +1 -0
- package/_cjs/Observable/api/windowToggle.cjs +92 -0
- package/_cjs/Observable/api/windowToggle.cjs.map +1 -0
- package/_cjs/Observable/api/windowWhen.cjs +68 -0
- package/_cjs/Observable/api/windowWhen.cjs.map +1 -0
- package/_cjs/Observable/api.cjs +2558 -0
- package/_cjs/Observable/api.cjs.map +1 -0
- package/_cjs/Observable/definition.cjs +76 -0
- package/_cjs/Observable/definition.cjs.map +1 -0
- package/_cjs/Observable/dom/animationFrames.cjs +51 -0
- package/_cjs/Observable/dom/animationFrames.cjs.map +1 -0
- package/_cjs/Observable/instances.cjs +6 -0
- package/_cjs/Observable/instances.cjs.map +1 -0
- package/_cjs/Observable.cjs +253 -0
- package/_cjs/Observable.cjs.map +1 -0
- package/_cjs/Observer.cjs +6 -0
- package/_cjs/Observer.cjs.map +1 -0
- package/_cjs/Operator.cjs +83 -0
- package/_cjs/Operator.cjs.map +1 -0
- package/_cjs/Scheduler.cjs +62 -0
- package/_cjs/Scheduler.cjs.map +1 -0
- package/_cjs/Subject.cjs +228 -0
- package/_cjs/Subject.cjs.map +1 -0
- package/_cjs/Subscriber.cjs +172 -0
- package/_cjs/Subscriber.cjs.map +1 -0
- package/_cjs/Subscription.cjs +174 -0
- package/_cjs/Subscription.cjs.map +1 -0
- package/_cjs/demo.cjs +40 -0
- package/_cjs/demo.cjs.map +1 -0
- package/_cjs/global.cjs +4 -0
- package/_cjs/global.cjs.map +1 -0
- package/_cjs/index.cjs +65 -0
- package/_cjs/index.cjs.map +1 -0
- package/_cjs/internal/animationFrameProvider.cjs +51 -0
- package/_cjs/internal/animationFrameProvider.cjs.map +1 -0
- package/_cjs/internal/args.cjs +26 -0
- package/_cjs/internal/args.cjs.map +1 -0
- package/_cjs/internal/intervalProvider.cjs +27 -0
- package/_cjs/internal/intervalProvider.cjs.map +1 -0
- package/_cjs/internal/performanceTimestampProvider.cjs +15 -0
- package/_cjs/internal/performanceTimestampProvider.cjs.map +1 -0
- package/_cjs/internal/timeoutProvider.cjs +27 -0
- package/_cjs/internal/timeoutProvider.cjs.map +1 -0
- package/_cjs/internal/timestampProvider.cjs +15 -0
- package/_cjs/internal/timestampProvider.cjs.map +1 -0
- package/_cjs/internal/util.cjs +107 -0
- package/_cjs/internal/util.cjs.map +1 -0
- package/_mjs/Action.mjs +14 -0
- package/_mjs/Action.mjs.map +1 -0
- package/_mjs/AnimationFrameAction.mjs +33 -0
- package/_mjs/AnimationFrameAction.mjs.map +1 -0
- package/_mjs/AnimationFrameScheduler.mjs +36 -0
- package/_mjs/AnimationFrameScheduler.mjs.map +1 -0
- package/_mjs/AsyncAction.mjs +99 -0
- package/_mjs/AsyncAction.mjs.map +1 -0
- package/_mjs/AsyncScheduler.mjs +45 -0
- package/_mjs/AsyncScheduler.mjs.map +1 -0
- package/_mjs/BehaviorSubject.mjs +38 -0
- package/_mjs/BehaviorSubject.mjs.map +1 -0
- package/_mjs/Notification.mjs +80 -0
- package/_mjs/Notification.mjs.map +1 -0
- package/_mjs/Observable/api/connect.mjs +21 -0
- package/_mjs/Observable/api/connect.mjs.map +1 -0
- package/_mjs/Observable/api/connectable.mjs +45 -0
- package/_mjs/Observable/api/connectable.mjs.map +1 -0
- package/_mjs/Observable/api/fromCallback.mjs +60 -0
- package/_mjs/Observable/api/fromCallback.mjs.map +1 -0
- package/_mjs/Observable/api/fromEvent.mjs +10 -0
- package/_mjs/Observable/api/fromEvent.mjs.map +1 -0
- package/_mjs/Observable/api/index.mjs +15 -0
- package/_mjs/Observable/api/index.mjs.map +1 -0
- package/_mjs/Observable/api/race.mjs +32 -0
- package/_mjs/Observable/api/race.mjs.map +1 -0
- package/_mjs/Observable/api/raceWith.mjs +12 -0
- package/_mjs/Observable/api/raceWith.mjs.map +1 -0
- package/_mjs/Observable/api/repeatWhen.mjs +57 -0
- package/_mjs/Observable/api/repeatWhen.mjs.map +1 -0
- package/_mjs/Observable/api/retryWhen.mjs +45 -0
- package/_mjs/Observable/api/retryWhen.mjs.map +1 -0
- package/_mjs/Observable/api/share.mjs +97 -0
- package/_mjs/Observable/api/share.mjs.map +1 -0
- package/_mjs/Observable/api/window.mjs +40 -0
- package/_mjs/Observable/api/window.mjs.map +1 -0
- package/_mjs/Observable/api/windowCount.mjs +50 -0
- package/_mjs/Observable/api/windowCount.mjs.map +1 -0
- package/_mjs/Observable/api/windowTime.mjs +73 -0
- package/_mjs/Observable/api/windowTime.mjs.map +1 -0
- package/_mjs/Observable/api/windowToggle.mjs +77 -0
- package/_mjs/Observable/api/windowToggle.mjs.map +1 -0
- package/_mjs/Observable/api/windowWhen.mjs +54 -0
- package/_mjs/Observable/api/windowWhen.mjs.map +1 -0
- package/_mjs/Observable/api.mjs +2291 -0
- package/_mjs/Observable/api.mjs.map +1 -0
- package/_mjs/Observable/definition.mjs +54 -0
- package/_mjs/Observable/definition.mjs.map +1 -0
- package/_mjs/Observable/dom/animationFrames.mjs +36 -0
- package/_mjs/Observable/dom/animationFrames.mjs.map +1 -0
- package/_mjs/Observable/instances.mjs +2 -0
- package/_mjs/Observable/instances.mjs.map +1 -0
- package/_mjs/Observable.mjs +25 -0
- package/_mjs/Observable.mjs.map +1 -0
- package/_mjs/Observer.mjs +2 -0
- package/_mjs/Observer.mjs.map +1 -0
- package/_mjs/Operator.mjs +63 -0
- package/_mjs/Operator.mjs.map +1 -0
- package/_mjs/Scheduler.mjs +41 -0
- package/_mjs/Scheduler.mjs.map +1 -0
- package/_mjs/Subject.mjs +204 -0
- package/_mjs/Subject.mjs.map +1 -0
- package/_mjs/Subscriber.mjs +147 -0
- package/_mjs/Subscriber.mjs.map +1 -0
- package/_mjs/Subscription.mjs +148 -0
- package/_mjs/Subscription.mjs.map +1 -0
- package/_mjs/demo.mjs +30 -0
- package/_mjs/demo.mjs.map +1 -0
- package/_mjs/global.mjs +2 -0
- package/_mjs/global.mjs.map +1 -0
- package/_mjs/index.mjs +15 -0
- package/_mjs/index.mjs.map +1 -0
- package/_mjs/internal/animationFrameProvider.mjs +38 -0
- package/_mjs/internal/animationFrameProvider.mjs.map +1 -0
- package/_mjs/internal/args.mjs +13 -0
- package/_mjs/internal/args.mjs.map +1 -0
- package/_mjs/internal/intervalProvider.mjs +20 -0
- package/_mjs/internal/intervalProvider.mjs.map +1 -0
- package/_mjs/internal/performanceTimestampProvider.mjs +8 -0
- package/_mjs/internal/performanceTimestampProvider.mjs.map +1 -0
- package/_mjs/internal/timeoutProvider.mjs +20 -0
- package/_mjs/internal/timeoutProvider.mjs.map +1 -0
- package/_mjs/internal/timestampProvider.mjs +8 -0
- package/_mjs/internal/timestampProvider.mjs.map +1 -0
- package/_mjs/internal/util.mjs +76 -0
- package/_mjs/internal/util.mjs.map +1 -0
- package/_src/Action.ts +10 -0
- package/_src/AnimationFrameAction.ts +27 -0
- package/_src/AnimationFrameScheduler.ts +30 -0
- package/_src/AsyncAction.ts +93 -0
- package/_src/AsyncScheduler.ts +41 -0
- package/_src/BehaviorSubject.ts +28 -0
- package/_src/Notification.ts +91 -0
- package/_src/Observable/api/connect.ts +23 -0
- package/_src/Observable/api/connectable.ts +52 -0
- package/_src/Observable/api/fromCallback.ts +57 -0
- package/_src/Observable/api/fromEvent.ts +12 -0
- package/_src/Observable/api/index.ts +14 -0
- package/_src/Observable/api/race.ts +31 -0
- package/_src/Observable/api/raceWith.ts +15 -0
- package/_src/Observable/api/repeatWhen.ts +63 -0
- package/_src/Observable/api/retryWhen.ts +47 -0
- package/_src/Observable/api/share.ts +107 -0
- package/_src/Observable/api/window.ts +44 -0
- package/_src/Observable/api/windowCount.ts +56 -0
- package/_src/Observable/api/windowTime.ts +102 -0
- package/_src/Observable/api/windowToggle.ts +84 -0
- package/_src/Observable/api/windowWhen.ts +59 -0
- package/_src/Observable/api.ts +2749 -0
- package/_src/Observable/definition.ts +69 -0
- package/_src/Observable/dom/animationFrames.ts +33 -0
- package/_src/Observable/instances.ts +106 -0
- package/_src/Observable.ts +27 -0
- package/_src/Observer.ts +5 -0
- package/_src/Operator.ts +73 -0
- package/_src/Scheduler.ts +52 -0
- package/_src/Subject.ts +171 -0
- package/_src/Subscriber.ts +130 -0
- package/_src/Subscription.ts +143 -0
- package/_src/demo.ts +29 -0
- package/_src/global.ts +141 -0
- package/_src/index.ts +14 -0
- package/_src/internal/animationFrameProvider.ts +37 -0
- package/_src/internal/args.ts +11 -0
- package/_src/internal/intervalProvider.ts +27 -0
- package/_src/internal/performanceTimestampProvider.ts +12 -0
- package/_src/internal/timeoutProvider.ts +27 -0
- package/_src/internal/timestampProvider.ts +14 -0
- package/_src/internal/util.ts +94 -0
- package/demo.d.ts +1 -0
- package/global.d.ts +125 -0
- package/index.d.ts +14 -0
- package/internal/animationFrameProvider.d.ts +12 -0
- package/internal/args.d.ts +3 -0
- package/internal/intervalProvider.d.ts +12 -0
- package/internal/performanceTimestampProvider.d.ts +6 -0
- package/internal/timeoutProvider.d.ts +12 -0
- package/internal/timestampProvider.d.ts +7 -0
- package/internal/util.d.ts +28 -0
- package/package.json +16 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
export class AnimationFrameScheduler extends AsyncScheduler {
|
|
3
|
+
public flush(action?: AsyncAction<any>): void {
|
|
4
|
+
this.active = true;
|
|
5
|
+
this.scheduled = undefined;
|
|
6
|
+
|
|
7
|
+
const { actions } = this;
|
|
8
|
+
let error: any;
|
|
9
|
+
let index = -1;
|
|
10
|
+
action = action || actions.shift()!;
|
|
11
|
+
const count = actions.length;
|
|
12
|
+
|
|
13
|
+
do {
|
|
14
|
+
if ((error = action.execute(action.state, action.delay!))) {
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
} while (++index < count && (action = actions.shift()));
|
|
18
|
+
|
|
19
|
+
this.active = false;
|
|
20
|
+
|
|
21
|
+
if (error) {
|
|
22
|
+
while (++index < count && (action = actions.shift())) {
|
|
23
|
+
action.unsubscribe();
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const animationFrameScheduler = new AnimationFrameScheduler(AnimationFrameAction);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { intervalProvider } from "@fncts/observable/internal/intervalProvider";
|
|
2
|
+
import { arrayRemove } from "@fncts/observable/internal/util";
|
|
3
|
+
|
|
4
|
+
export class AsyncAction<A> extends Action<A> {
|
|
5
|
+
public id: any;
|
|
6
|
+
public state?: A;
|
|
7
|
+
public delay: number | undefined;
|
|
8
|
+
protected pending = false;
|
|
9
|
+
|
|
10
|
+
constructor(protected scheduler: AsyncScheduler, protected work: (this: SchedulerAction<A>, state?: A) => void) {
|
|
11
|
+
super(scheduler, work);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
schedule(state?: A, delay = 0): Subscription {
|
|
15
|
+
if (this.closed) {
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.state = state;
|
|
20
|
+
|
|
21
|
+
const id = this.id;
|
|
22
|
+
const scheduler = this.scheduler;
|
|
23
|
+
|
|
24
|
+
if (id != null) {
|
|
25
|
+
this.id = this.recycleAsyncId(scheduler, id, delay);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.pending = true;
|
|
29
|
+
this.delay = delay;
|
|
30
|
+
this.id = this.id || this.requestAsyncId(scheduler, this.id, delay);
|
|
31
|
+
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
protected requestAsyncId(scheduler: AsyncScheduler, _id: any, delay = 0): any {
|
|
36
|
+
return intervalProvider.setInterval(scheduler.flush.bind(scheduler, this), delay);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
protected recycleAsyncId(_scheduler: AsyncScheduler, id: any, delay: number | null = 0): any {
|
|
40
|
+
if (delay != null && this.delay === delay && this.pending === false) {
|
|
41
|
+
return id;
|
|
42
|
+
}
|
|
43
|
+
intervalProvider.clearInterval(id);
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public execute(state: A, delay: number): unknown {
|
|
48
|
+
if (this.closed) {
|
|
49
|
+
throw new Error("executing a cancelled action");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.pending = false;
|
|
53
|
+
const error = this.executeInternal(state, delay);
|
|
54
|
+
if (error) {
|
|
55
|
+
return error;
|
|
56
|
+
} else if (this.pending === false && this.id != null) {
|
|
57
|
+
this.id = this.recycleAsyncId(this.scheduler, this.id, null);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
protected executeInternal(state: A, _delay: number): unknown {
|
|
62
|
+
let errored = false;
|
|
63
|
+
let errorValue: unknown;
|
|
64
|
+
try {
|
|
65
|
+
this.work(state);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
errored = true;
|
|
68
|
+
errorValue = e ? e : new Error("Scheduled action threw falsy error");
|
|
69
|
+
}
|
|
70
|
+
if (errored) {
|
|
71
|
+
this.unsubscribe();
|
|
72
|
+
return errorValue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
unsubscribe() {
|
|
77
|
+
if (!this.closed) {
|
|
78
|
+
const { id, scheduler } = this;
|
|
79
|
+
const { actions } = scheduler;
|
|
80
|
+
|
|
81
|
+
this.work = this.state = this.scheduler = null!;
|
|
82
|
+
this.pending = false;
|
|
83
|
+
|
|
84
|
+
arrayRemove(actions, this);
|
|
85
|
+
if (id != null) {
|
|
86
|
+
this.id = this.recycleAsyncId(scheduler, id, null);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.delay = null!;
|
|
90
|
+
super.unsubscribe();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class AsyncScheduler extends Scheduler {
|
|
2
|
+
public actions: Array<AsyncAction<any>> = [];
|
|
3
|
+
|
|
4
|
+
active = false;
|
|
5
|
+
scheduled: any = undefined;
|
|
6
|
+
|
|
7
|
+
constructor(actionConstructor: typeof Action, now: () => number = Scheduler.now) {
|
|
8
|
+
super(actionConstructor, now);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
flush(action: AsyncAction<any>) {
|
|
12
|
+
const { actions } = this;
|
|
13
|
+
|
|
14
|
+
if (this.active) {
|
|
15
|
+
actions.push(action);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let error: unknown;
|
|
20
|
+
this.active = true;
|
|
21
|
+
|
|
22
|
+
do {
|
|
23
|
+
if ((error = action.execute(action.state, action.delay!))) {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
// eslint-disable-next-line no-param-reassign
|
|
27
|
+
} while ((action = actions.shift()!));
|
|
28
|
+
|
|
29
|
+
this.active = false;
|
|
30
|
+
|
|
31
|
+
if (error) {
|
|
32
|
+
// eslint-disable-next-line no-param-reassign
|
|
33
|
+
while ((action = actions.shift()!)) {
|
|
34
|
+
action.unsubscribe();
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const asyncScheduler = new AsyncScheduler(AsyncAction);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class BehaviorSubject<E, A> extends Subject<E, A> {
|
|
2
|
+
constructor(private _value: A) {
|
|
3
|
+
super();
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
get value(): A {
|
|
7
|
+
return this.getValue();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getValue(): A {
|
|
11
|
+
const { hasError, thrownError, _value } = this;
|
|
12
|
+
if (hasError) {
|
|
13
|
+
throw thrownError;
|
|
14
|
+
}
|
|
15
|
+
this.throwIfClosed();
|
|
16
|
+
return _value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
protected subscribeInternal(subscriber: Subscriber<E, A>) {
|
|
20
|
+
const subscription = super.subscribe(subscriber);
|
|
21
|
+
!subscription.closed && subscriber.next(this._value);
|
|
22
|
+
return subscription;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
next(value: A): void {
|
|
26
|
+
super.next((this._value = value));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export const NextTypeId = Symbol.for("fncts.observable.Notification.Next");
|
|
2
|
+
export type NextTypeId = typeof NextTypeId;
|
|
3
|
+
|
|
4
|
+
export class Next<A> {
|
|
5
|
+
readonly _tag = "Next";
|
|
6
|
+
readonly [NextTypeId]: NextTypeId = NextTypeId;
|
|
7
|
+
constructor(readonly value: A) {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const FailTypeId = Symbol.for("fncts.observable.Notification.Fail");
|
|
11
|
+
export type FailTypeId = typeof FailTypeId;
|
|
12
|
+
|
|
13
|
+
export class Fail<E> {
|
|
14
|
+
readonly _tag = "Fail";
|
|
15
|
+
readonly [FailTypeId]: FailTypeId = FailTypeId;
|
|
16
|
+
constructor(readonly error: Cause<E>) {}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const CompleteTypeId = Symbol.for("fncts.observable.Notification.Complete");
|
|
20
|
+
export type CompleteTypeId = typeof CompleteTypeId;
|
|
21
|
+
|
|
22
|
+
export class Complete {
|
|
23
|
+
readonly _tag = "Complete";
|
|
24
|
+
readonly [CompleteTypeId]: CompleteTypeId = CompleteTypeId;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const COMPLETE = new Complete();
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @tsplus type fncts.observable.Notification
|
|
31
|
+
*/
|
|
32
|
+
export type Notification<E, A> = Next<A> | Fail<E> | Complete;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @tsplus type fncts.observable.NotificationOps
|
|
36
|
+
*/
|
|
37
|
+
export interface NotificationOps {}
|
|
38
|
+
|
|
39
|
+
export const Notification: NotificationOps = {};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @tsplus static fncts.observable.NotificationOps next
|
|
43
|
+
*/
|
|
44
|
+
export function next<E = never, A = never>(value: A): Notification<E, A> {
|
|
45
|
+
return new Next(value);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @tsplus static fncts.observable.NotificationOps error
|
|
50
|
+
*/
|
|
51
|
+
export function error<E = never, A = never>(error: Cause<E>): Notification<E, A> {
|
|
52
|
+
return new Fail(error);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @tsplus static fncts.observable.NotificationOps complete
|
|
57
|
+
*/
|
|
58
|
+
export function complete<E = never, A = never>(): Notification<E, A> {
|
|
59
|
+
return COMPLETE;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @tsplus fluent fncts.observable.Notification match
|
|
64
|
+
*/
|
|
65
|
+
export function match_<E, A, B, C, D, F>(
|
|
66
|
+
fa: Notification<E, A>,
|
|
67
|
+
onNext: (a: A) => B,
|
|
68
|
+
onFail: (e: Cause<E>) => C,
|
|
69
|
+
onComplete: () => F,
|
|
70
|
+
): B | C | D | F {
|
|
71
|
+
switch (fa._tag) {
|
|
72
|
+
case "Next":
|
|
73
|
+
return onNext(fa.value);
|
|
74
|
+
case "Fail":
|
|
75
|
+
return onFail(fa.error);
|
|
76
|
+
case "Complete":
|
|
77
|
+
return onComplete();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @tsplus fluent fncts.observable.Notification observe
|
|
83
|
+
*/
|
|
84
|
+
export function observe_<E, A>(notification: Notification<E, A>, observer: Partial<Observer<E, A>>): void {
|
|
85
|
+
return match_(
|
|
86
|
+
notification,
|
|
87
|
+
(a) => observer.next?.(a),
|
|
88
|
+
(e) => observer.error?.(e),
|
|
89
|
+
() => observer.complete?.(),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ConnectConfig<E, A> {
|
|
2
|
+
readonly connector: () => SubjectLike<E, A>;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const DEFAULT_CONNECT_CONFIG: ConnectConfig<any, any> = {
|
|
6
|
+
connector: () => new Subject(),
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @tsplus fluent fncts.observable.Observable connect
|
|
11
|
+
*/
|
|
12
|
+
export function connect<E, A, E1, B>(
|
|
13
|
+
fa: Observable<E, A>,
|
|
14
|
+
selector: (shared: Observable<E, A>) => ObservableInput<E1, B>,
|
|
15
|
+
config: ConnectConfig<E, A> = DEFAULT_CONNECT_CONFIG,
|
|
16
|
+
): Observable<E | E1, B> {
|
|
17
|
+
const { connector } = config;
|
|
18
|
+
return operate_(fa, (source, subscriber) => {
|
|
19
|
+
const subject = connector();
|
|
20
|
+
Observable.from(selector(Observable.fromSubscribable(subject))).subscribe(subscriber);
|
|
21
|
+
subscriber.add(source.subscribe(subject));
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface ConnectableLike<E, A> extends Observable<E, A> {
|
|
2
|
+
connect(): Subscription;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface ConnectableConfig<E, A> {
|
|
6
|
+
readonly connector: () => SubjectLike<E, A>;
|
|
7
|
+
readonly resetOnDisconnect?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_CONFIG: ConnectableConfig<any, any> = {
|
|
11
|
+
connector: () => new Subject(),
|
|
12
|
+
resetOnDisconnect: false,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class Connectable<E, A> extends Observable<E, A> implements ConnectableLike<E, A> {
|
|
16
|
+
protected connection: Subscription | null;
|
|
17
|
+
protected connector: () => SubjectLike<E, A>;
|
|
18
|
+
protected resetOnDisconnect: boolean;
|
|
19
|
+
protected source: Observable<E, A>;
|
|
20
|
+
protected subject: SubjectLike<E, A>;
|
|
21
|
+
constructor(source: ObservableInput<E, A>, config: ConnectableConfig<E, A>) {
|
|
22
|
+
const { connector, resetOnDisconnect = true } = config;
|
|
23
|
+
const subject = connector();
|
|
24
|
+
super((subscriber) => {
|
|
25
|
+
return subject.subscribe(subscriber);
|
|
26
|
+
});
|
|
27
|
+
this.connection = null;
|
|
28
|
+
this.subject = subject;
|
|
29
|
+
this.connector = connector;
|
|
30
|
+
this.resetOnDisconnect = resetOnDisconnect;
|
|
31
|
+
this.source = Observable.from(source);
|
|
32
|
+
}
|
|
33
|
+
connect() {
|
|
34
|
+
if (!this.connection || this.connection.closed) {
|
|
35
|
+
this.connection = Observable.defer(this.source).subscribe(this.subject);
|
|
36
|
+
if (this.resetOnDisconnect) {
|
|
37
|
+
this.connection.add(() => (this.subject = this.connector()));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return this.connection;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @tsplus fluent fncts.observable.Observable connectable
|
|
46
|
+
*/
|
|
47
|
+
export function connectable<E, A>(
|
|
48
|
+
source: ObservableInput<E, A>,
|
|
49
|
+
config: ConnectableConfig<E, A> = DEFAULT_CONFIG,
|
|
50
|
+
): Connectable<E, A> {
|
|
51
|
+
return new Connectable(source, config);
|
|
52
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tsplus static fncts.observable.ObservableOps fromCallback
|
|
3
|
+
*/
|
|
4
|
+
export function fromCallback<A extends ReadonlyArray<unknown>, R extends ReadonlyArray<unknown>>(
|
|
5
|
+
callbackFunc: (...args: [...A, (...res: R) => void]) => void,
|
|
6
|
+
): (...args: A) => Observable<unknown, R> {
|
|
7
|
+
// @ts-expect-error
|
|
8
|
+
return fromCallbackInternal(false, callbackFunc);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @tsplus static fncts.observable.ObservableOps fromNodeCallback
|
|
13
|
+
*/
|
|
14
|
+
export function fromNodeCallback<E, A extends ReadonlyArray<unknown>, R extends ReadonlyArray<unknown>>(
|
|
15
|
+
callbackFunc: (...args: [...A, (err: E, ...res: R) => void]) => void,
|
|
16
|
+
): (...args: A) => Observable<Exclude<E, null | undefined>, R extends [] ? void : R extends [any] ? R[0] : R> {
|
|
17
|
+
// @ts-expect-error
|
|
18
|
+
return fromCallbackInternal(true, callbackFunc);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function fromCallbackInternal(isNodeStyle: boolean, callbackFunc: any): (...args: any[]) => Observable<unknown, any> {
|
|
22
|
+
return function (this: any, ...args: any[]): Observable<unknown, any> {
|
|
23
|
+
const subject = new AsyncSubject<any, any>();
|
|
24
|
+
let uninitialized = true;
|
|
25
|
+
return new Observable((subscriber) => {
|
|
26
|
+
const subs = subject.subscribe(subscriber);
|
|
27
|
+
if (uninitialized) {
|
|
28
|
+
uninitialized = false;
|
|
29
|
+
let isAsync = false;
|
|
30
|
+
let isComplete = false;
|
|
31
|
+
callbackFunc.apply(this, [
|
|
32
|
+
...args,
|
|
33
|
+
(...results: any[]) => {
|
|
34
|
+
if (isNodeStyle) {
|
|
35
|
+
const err = results.shift();
|
|
36
|
+
if (err != null) {
|
|
37
|
+
subject.error(err);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
subject.next(1 < results.length ? results : results[0]);
|
|
42
|
+
isComplete = true;
|
|
43
|
+
if (isAsync) {
|
|
44
|
+
subject.complete();
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
]);
|
|
48
|
+
if (isComplete) {
|
|
49
|
+
subject.complete();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
isAsync = true;
|
|
53
|
+
}
|
|
54
|
+
return subs;
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type EventHandler = (...args: any[]) => void;
|
|
2
|
+
|
|
3
|
+
export function fromEvent<A extends ReadonlyArray<unknown>>(
|
|
4
|
+
addHandler: (handler: (...args: A) => void) => any,
|
|
5
|
+
removeHandler?: (handler: EventHandler, signal?: any) => void,
|
|
6
|
+
): Observable<never, A extends [infer X] ? X : A> {
|
|
7
|
+
return new Observable((subscriber) => {
|
|
8
|
+
const handler = (...e: any[]) => subscriber.next(e.length === 1 ? e[0] : e);
|
|
9
|
+
const retValue = addHandler(handler as any);
|
|
10
|
+
return removeHandler && (() => removeHandler(handler, retValue));
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./connect.js";
|
|
2
|
+
export * from "./connectable.js";
|
|
3
|
+
export * from "./fromCallback.js";
|
|
4
|
+
export * from "./fromEvent.js";
|
|
5
|
+
export * from "./race.js";
|
|
6
|
+
export * from "./raceWith.js";
|
|
7
|
+
export * from "./repeatWhen.js";
|
|
8
|
+
export * from "./retryWhen.js";
|
|
9
|
+
export * from "./share.js";
|
|
10
|
+
export * from "./window.js";
|
|
11
|
+
export * from "./windowCount.js";
|
|
12
|
+
export * from "./windowTime.js";
|
|
13
|
+
export * from "./windowToggle.js";
|
|
14
|
+
export * from "./windowWhen.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tsplus static fncts.observable.ObservableOps race
|
|
3
|
+
*/
|
|
4
|
+
export function race<O extends ReadonlyArray<ObservableInput<any, any>>>(
|
|
5
|
+
...sources: O
|
|
6
|
+
): Observable<Observable.ErrorOf<O[number]>, Observable.TypeOf<O[number]>> {
|
|
7
|
+
return sources.length === 1 ? Observable.from(sources[0]!) : new Observable(raceInit(sources));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function raceInit<E, A>(sources: ReadonlyArray<ObservableInput<E, A>>) {
|
|
11
|
+
return (subscriber: Subscriber<E, A>) => {
|
|
12
|
+
let subscriptions: Subscription[] = [];
|
|
13
|
+
for (let i = 0; subscriptions && !subscriber.closed && i < sources.length; i++) {
|
|
14
|
+
subscriptions.push(
|
|
15
|
+
Observable.from(sources[i]!).subscribe(
|
|
16
|
+
operatorSubscriber(subscriber, {
|
|
17
|
+
next: (value) => {
|
|
18
|
+
if (subscriptions) {
|
|
19
|
+
for (let s = 0; s < subscriptions.length; s++) {
|
|
20
|
+
s !== i && subscriptions[s]!.unsubscribe();
|
|
21
|
+
}
|
|
22
|
+
subscriptions = null!;
|
|
23
|
+
}
|
|
24
|
+
subscriber.next(value);
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { raceInit } from "./race.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @tsplus fluent fncts.observable.Observablen raceWith
|
|
5
|
+
*/
|
|
6
|
+
export function raceWith_<E, A, O extends ReadonlyArray<ObservableInput<any, any>>>(
|
|
7
|
+
fa: Observable<E, A>,
|
|
8
|
+
...sources: O
|
|
9
|
+
): Observable<E | Observable.ErrorOf<O[number]>, A | Observable.TypeOf<O[number]>> {
|
|
10
|
+
return !sources.length
|
|
11
|
+
? fa
|
|
12
|
+
: fa.operate((source, subscriber) => {
|
|
13
|
+
raceInit([source, ...sources])(subscriber);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export function repeatWhen_<E, A, E1>(
|
|
2
|
+
fa: Observable<E, A>,
|
|
3
|
+
notifier: (notifications: Observable<never, void>) => Observable<E1, any>,
|
|
4
|
+
): Observable<E | E1, A> {
|
|
5
|
+
return fa.operate((source, subscriber) => {
|
|
6
|
+
let innerSub: Subscription | null;
|
|
7
|
+
let syncResub = false;
|
|
8
|
+
let completions$: Subject<never, void>;
|
|
9
|
+
let isNotifierComplete = false;
|
|
10
|
+
let isMainComplete = false;
|
|
11
|
+
|
|
12
|
+
const checkComplete = () => isMainComplete && isNotifierComplete && (subscriber.complete(), true);
|
|
13
|
+
|
|
14
|
+
const getCompletionSubject = () => {
|
|
15
|
+
if (!completions$) {
|
|
16
|
+
completions$ = new Subject();
|
|
17
|
+
notifier(completions$).subscribe(
|
|
18
|
+
operatorSubscriber(subscriber, {
|
|
19
|
+
next: () => {
|
|
20
|
+
if (innerSub) {
|
|
21
|
+
loop();
|
|
22
|
+
} else {
|
|
23
|
+
syncResub = true;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
complete: () => {
|
|
27
|
+
isNotifierComplete = true;
|
|
28
|
+
checkComplete();
|
|
29
|
+
},
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return completions$;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const loop = () => {
|
|
37
|
+
isMainComplete = false;
|
|
38
|
+
innerSub = source.subscribe(
|
|
39
|
+
operatorSubscriber(subscriber, {
|
|
40
|
+
complete: () => {
|
|
41
|
+
isMainComplete = true;
|
|
42
|
+
!checkComplete() && getCompletionSubject().next();
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (syncResub) {
|
|
48
|
+
innerSub.unsubscribe();
|
|
49
|
+
innerSub = null;
|
|
50
|
+
syncResub = false;
|
|
51
|
+
loop();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
loop();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function repeatWhen<E1>(
|
|
60
|
+
notifier: (notifications: Observable<never, void>) => Observable<E1, any>,
|
|
61
|
+
): <E, A>(fa: Observable<E, A>) => Observable<E | E1, A> {
|
|
62
|
+
return (fa) => repeatWhen_(fa, notifier);
|
|
63
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tsplus fluent fncts.observable.Observable retryWhen
|
|
3
|
+
*/
|
|
4
|
+
export function retryWhen_<E, A, E1>(
|
|
5
|
+
fa: Observable<E, A>,
|
|
6
|
+
notifier: (errors: Observable<never, Cause<E>>) => Observable<E1, any>,
|
|
7
|
+
): Observable<E | E1, A> {
|
|
8
|
+
return operate_(fa, (source, subscriber) => {
|
|
9
|
+
let innerSub: Subscription | null;
|
|
10
|
+
let syncResub = false;
|
|
11
|
+
let defects$: Subject<never, any>;
|
|
12
|
+
|
|
13
|
+
const loop = () => {
|
|
14
|
+
innerSub = source.subscribe(
|
|
15
|
+
operatorSubscriber(subscriber, {
|
|
16
|
+
error: (err) => {
|
|
17
|
+
if (!defects$) {
|
|
18
|
+
defects$ = new Subject();
|
|
19
|
+
notifier(defects$).subscribe(
|
|
20
|
+
operatorSubscriber(subscriber, {
|
|
21
|
+
next: () => (innerSub ? loop() : (syncResub = true)),
|
|
22
|
+
}),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
if (defects$) {
|
|
26
|
+
defects$.next(err);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
if (syncResub) {
|
|
32
|
+
innerSub.unsubscribe();
|
|
33
|
+
innerSub = null;
|
|
34
|
+
syncResub = false;
|
|
35
|
+
loop();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
loop();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function retryWhen<E1>(
|
|
44
|
+
notifier: (errors: Observable<never, any>) => Observable<E1, any>,
|
|
45
|
+
): <E, A>(fa: Observable<E, A>) => Observable<E | E1, A> {
|
|
46
|
+
return (fa) => retryWhen_(fa, notifier);
|
|
47
|
+
}
|