@platform/state
Version:
A small, simple, strongly typed, [rx/observable] state-machine.
48 lines (47 loc) • 1.62 kB
JavaScript
import { takeUntil } from 'rxjs/operators';
import { is } from '../common';
export function create(factory) {
return (initial, dispose$) => {
const initialStateObjects = [];
initial = Object.keys(initial).reduce((acc, key) => {
const value = initial[key];
if (is.stateObject(value)) {
acc[key] = value.state;
initialStateObjects.push({ key, obj: value });
}
else {
acc[key] = value;
}
return acc;
}, {});
const store = factory(initial);
if (dispose$) {
dispose$.subscribe(() => api.dispose());
}
const change = (key, to) => store.change((draft) => (draft[key] = to));
const api = {
store,
get state() {
return store.state;
},
get changed$() {
return store.event.changed$;
},
add(key, subject) {
const isObservable = is.observable(subject);
const changed$ = isObservable
? subject
: subject.event.changed$;
if (!isObservable) {
const obj = subject;
change(key, obj.state);
}
changed$.pipe(takeUntil(store.dispose$)).subscribe((e) => change(key, e.to));
return api;
},
dispose: () => store.dispose(),
};
initialStateObjects.forEach(({ key, obj }) => api.add(key, obj));
return api;
};
}