fix(core): initial

This commit is contained in:
2019-02-21 21:48:39 +01:00
commit 1663e31a2e
16 changed files with 2032 additions and 0 deletions

5
ts/index.ts Normal file
View 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';

View 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() {}
}

View 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) {}
}

View 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);
}
}

View 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() {}
}

View 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
View File

@ -0,0 +1,7 @@
import { Observable } from 'rxjs';
const rxjsPart = {
Observable
};
export { rxjsPart };