UNPKG

2.38 kBJavaScriptView Raw
1import produce from 'immer';
2import { Subject } from 'rxjs';
3import { filter, map, share, takeUntil } from 'rxjs/operators';
4export class Store {
5 constructor(args) {
6 this._dispose$ = new Subject();
7 this._changing$ = new Subject();
8 this._changed$ = new Subject();
9 this._ = {
10 state: undefined,
11 };
12 this.dispose$ = this._dispose$.pipe(share());
13 this.changing$ = this._changing$.pipe(share());
14 this.changed$ = this._changed$.pipe(share());
15 this._.state = Object.assign({}, args.initial);
16 this._event$ = args.event$ || new Subject();
17 this.event$ = this._event$.pipe(takeUntil(this.dispose$), map((e) => this.toDispatchEvent(e)), share());
18 }
19 static create(args) {
20 return new Store(args);
21 }
22 dispose() {
23 this._dispose$.next();
24 this._dispose$.complete();
25 }
26 get isDisposed() {
27 return this._dispose$.isStopped;
28 }
29 get state() {
30 return Object.assign({}, this._.state);
31 }
32 dispatch(event) {
33 this._event$.next(event);
34 return this;
35 }
36 on(type) {
37 return this.event$.pipe(filter((e) => e.type === type), map((e) => e));
38 }
39 toDispatchEvent(event) {
40 const { type, payload } = event;
41 const from = this.state;
42 const result = {
43 type,
44 payload,
45 get state() {
46 return Object.assign({}, from);
47 },
48 change: (next) => {
49 const to = typeof next !== 'function'
50 ? Object.assign({}, next) : produce(from, (draft) => {
51 next(draft);
52 return undefined;
53 });
54 let isCancelled = false;
55 const change = { type, event, from, to };
56 this._changing$.next({
57 change,
58 isCancelled,
59 cancel: () => (isCancelled = true),
60 });
61 if (isCancelled) {
62 return result;
63 }
64 this._.state = to;
65 this._changed$.next(change);
66 return result;
67 },
68 dispatch: (event) => {
69 this.dispatch(event);
70 return result;
71 },
72 };
73 return result;
74 }
75}