fix(core): initial
This commit is contained in:
5
ts/index.ts
Normal file
5
ts/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './smartstate.classes.smartstate';
|
||||
export * from './smartstate.classes.statepart';
|
||||
export * from './smartstate.classes.statecollection';
|
||||
export * from './smartstate.classes.stateaction';
|
||||
export * from './smartstate.classes.stateobservable';
|
47
ts/smartstate.classes.smartstate.ts
Normal file
47
ts/smartstate.classes.smartstate.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import * as plugins from './smartstate.plugins';
|
||||
import { StatePart } from './smartstate.classes.statepart';
|
||||
|
||||
/**
|
||||
* Smartstate takes care of providing state
|
||||
*/
|
||||
export class Smartstate<StatePartNameType> {
|
||||
statePartMap: { [key: string]: StatePart<StatePartNameType, any> } = {};
|
||||
|
||||
constructor() {}
|
||||
|
||||
getStatePart<PayloadType>(
|
||||
statePartNameArg: StatePartNameType,
|
||||
initialArg?: PayloadType
|
||||
): StatePart<StatePartNameType, PayloadType> {
|
||||
if (this.statePartMap[statePartNameArg as any]) {
|
||||
if (initialArg) {
|
||||
throw new Error(
|
||||
`${statePartNameArg} already exists, yet you try to set an initial state again`
|
||||
);
|
||||
}
|
||||
return this.statePartMap[statePartNameArg as any];
|
||||
} else {
|
||||
if (!initialArg) {
|
||||
throw new Error(
|
||||
`${statePartNameArg} does not yet exist, yet you don't provide an initial state`
|
||||
);
|
||||
}
|
||||
return this.createStatePart<PayloadType>(statePartNameArg, initialArg);
|
||||
}
|
||||
}
|
||||
|
||||
private createStatePart<PayloadType>(
|
||||
statePartName: StatePartNameType,
|
||||
initialPayloadArg: PayloadType
|
||||
): StatePart<StatePartNameType, PayloadType> {
|
||||
const newState = new StatePart<StatePartNameType, PayloadType>(statePartName);
|
||||
newState.setState(initialPayloadArg);
|
||||
this.statePartMap[statePartName as any] = newState;
|
||||
return newState;
|
||||
}
|
||||
|
||||
/**
|
||||
* dispatches an action on the main level
|
||||
*/
|
||||
dispatch() {}
|
||||
}
|
8
ts/smartstate.classes.stateaction.ts
Normal file
8
ts/smartstate.classes.stateaction.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import * as plugins from './smartstate.plugins';
|
||||
|
||||
/**
|
||||
* an actionmodifier for the state
|
||||
*/
|
||||
export class StateAction<StatePayload> {
|
||||
constructor(public actionDef: (stateArg: StatePayload) => StatePayload) {}
|
||||
}
|
12
ts/smartstate.classes.statecollection.ts
Normal file
12
ts/smartstate.classes.statecollection.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import * as plugins from './smartstate.plugins';
|
||||
import { StatePart } from './smartstate.classes.statepart';
|
||||
|
||||
/**
|
||||
* A StatePartCollection is a collection of StateParts.
|
||||
* It can be used for expressing interest in a certain set of StateParts.
|
||||
*/
|
||||
export class StatePartCollection<StatePartNameType, T> extends StatePart<StatePartNameType, T> {
|
||||
constructor(nameArg: StatePartNameType) {
|
||||
super(nameArg);
|
||||
}
|
||||
}
|
13
ts/smartstate.classes.stateobservable.ts
Normal file
13
ts/smartstate.classes.stateobservable.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import * as plugins from './smartstate.plugins';
|
||||
|
||||
/**
|
||||
* State observable observes a StatePart and notifies everyone interested
|
||||
*/
|
||||
export class StateObservable {
|
||||
/**
|
||||
* creates an observable from a StateCollection
|
||||
*/
|
||||
public static fromStatePartCollection(filterArg?: () => any) {}
|
||||
|
||||
constructor() {}
|
||||
}
|
63
ts/smartstate.classes.statepart.ts
Normal file
63
ts/smartstate.classes.statepart.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import * as plugins from './smartstate.plugins';
|
||||
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { startWith, takeUntil, map } from 'rxjs/operators';
|
||||
|
||||
import { StateAction } from './smartstate.classes.stateaction';
|
||||
|
||||
export class StatePart<StatePartNameType, PayloadType> {
|
||||
name: StatePartNameType;
|
||||
state = new Subject<PayloadType>();
|
||||
stateStore: PayloadType;
|
||||
|
||||
constructor(nameArg: StatePartNameType) {
|
||||
this.name = nameArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the state from the state store
|
||||
*/
|
||||
getState(): PayloadType {
|
||||
return this.stateStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the stateStore to the new state
|
||||
* @param newStateArg
|
||||
*/
|
||||
setState(newStateArg: PayloadType) {
|
||||
this.stateStore = newStateArg;
|
||||
this.notifyChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* notifies of a change on the state
|
||||
*/
|
||||
notifyChange() {
|
||||
this.state.next(this.stateStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* selects a state or a substate
|
||||
*/
|
||||
select<T = PayloadType>(selectorFn?: (state: PayloadType) => T): Observable<T> {
|
||||
if (!selectorFn) {
|
||||
selectorFn = (state: PayloadType) => <T>(<any>state);
|
||||
}
|
||||
|
||||
const mapped = this.state.pipe(
|
||||
startWith(this.getState()),
|
||||
map(selectorFn)
|
||||
);
|
||||
|
||||
return mapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* dispatches an action on the statepart level
|
||||
*/
|
||||
async dispatch(stateAction: StateAction<PayloadType>) {
|
||||
const newState = stateAction.actionDef(this.getState());
|
||||
this.setState(newState);
|
||||
}
|
||||
}
|
7
ts/smartstate.plugins.ts
Normal file
7
ts/smartstate.plugins.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
const rxjsPart = {
|
||||
Observable
|
||||
};
|
||||
|
||||
export { rxjsPart };
|
Reference in New Issue
Block a user