rx-store-core
Version:
A Rxjs and Immutable based Type-safe state management tool
112 lines (94 loc) • 3.35 kB
text/typescript
import { BehaviorSubject } from "rxjs";
import { BS, ConstraintKeys, Reactive, ReactiveConfig } from "rx-store-types";
import { AsyncBeheviorSubjectWithValue } from "./util/AsyncBeheviorSubjectWithValue";
import { AsyncSubjectWithValue } from "./util/AsyncSubjectWithValue";
import { SubjectWithValue } from "./util/SubjectWithValue";
export class ReactiveImpl<S extends BS> implements Reactive<S> {
private dataSource:
| BehaviorSubject<{ [K in keyof S]: ReturnType<S[K]> }>
| SubjectWithValue<{ [K in keyof S]: ReturnType<S[K]> }>
| AsyncSubjectWithValue<{ [K in keyof S]: ReturnType<S[K]> }>;
constructor(private initiator: S, config: ReactiveConfig) {
this.dataSource = this.init(config);
}
private init({ fireOnCreate, schedule }: ReactiveConfig) {
const keys = Object.keys(this.initiator) as Array<keyof S>;
const initData = keys.reduce((acc, next) => {
acc[next] = this.initiator[next]();
return acc;
}, {} as { [K in keyof S]: ReturnType<S[K]> });
if (schedule === "async") {
return fireOnCreate
? new AsyncBeheviorSubjectWithValue(initData)
: new AsyncSubjectWithValue(initData);
}
return fireOnCreate
? new BehaviorSubject(initData)
: new SubjectWithValue(initData);
}
get<K extends keyof S>(key: K) {
return this.dataSource.value[key] as ReturnType<S[K]>;
}
set<KS extends keyof S>(updated: { [K in KS]: ReturnType<S[K]> }) {
const data = this.dataSource.value;
const keys = Object.keys(updated) as Array<KS>;
keys.forEach((k) => {
data[k] = updated[k];
});
this.dataSource.next(data);
}
reset<K extends keyof S>(key: K) {
const data = this.dataSource.value;
data[key] = this.initiator[key]();
this.dataSource.next(data);
}
resetMultiple<KS extends keyof S>(keys: ConstraintKeys<KS>) {
const data = this.dataSource.value;
const converted = keys as KS[];
converted.forEach((key) => {
data[key] = this.initiator[key]();
});
this.dataSource.next(data);
}
resetAll() {
const data = this.dataSource.value;
this.getAllKeys().forEach((key) => {
data[key] = this.initiator[key]();
});
this.dataSource.next(data);
}
source() {
return this.dataSource.asObservable();
}
getDefault<K extends keyof S>(key: K): ReturnType<S[K]> {
return this.initiator[key]();
}
getDefaults<KS extends keyof S>(keys: ConstraintKeys<KS>) {
const converted = keys as KS[];
return converted.reduce((acc, next) => {
acc[next] = this.getDefault(next);
return acc;
}, {} as { [k in KS]: ReturnType<S[k]> });
}
getDefaultAll = () => {
return this.getAllKeys().reduce((acc, next) => {
acc[next] = this.getDefault(next);
return acc;
}, {} as { [k in keyof S]: ReturnType<S[k]> });
};
getMultiple<KS extends keyof S>(keys: ConstraintKeys<KS>) {
const converted = keys as KS[];
return converted.reduce((acc, next) => {
acc[next] = this.get(next);
return acc;
}, {} as { [K in KS]: ReturnType<S[K]> });
}
getAll() {
return {
...this.dataSource.value,
};
}
getAllKeys(): Array<keyof S> {
return Object.keys(this.initiator);
}
}