@gongt/ts-stl-client
Version:
123 lines (103 loc) • 3.68 kB
text/typescript
import {createLogger} from "@gongt/ts-stl-library/debug/create-logger";
import {LOG_LEVEL} from "@gongt/ts-stl-library/debug/levels";
import {IAData, IReduxActionConstructor, ISingleReducer} from "./action";
import {IReducerInfo} from "./combine-reducers";
import {IState} from "./preload-state";
const silly = createLogger(LOG_LEVEL.SILLY, 'v-store');
export interface IVirtualStore<ValueInterface> {
getReducers?(): IReducerInfo<ValueInterface>[];
name: string;
defaultValue?: ValueInterface;
}
export interface IVirtualStoreConstructor<ValueInterface> {
new(): IVirtualStore<ValueInterface>;
name: string;
}
/** only use in this file */
export interface IVirtualStoreClass<ValueInterface> {
new(): VirtualStore<ValueInterface>;
name: string;
}
export function reduce<VI, IData extends IAData>
(Constructor: IVirtualStoreClass<VI>,
Action: IReduxActionConstructor<IData, VI>,
...reducer: ISingleReducer<VI, IData>[]) {
const vs = new Constructor;
return vs['reduce'](Action, ...reducer);
}
export function reduceAny<VI, IData extends IAData>
(Constructor: IVirtualStoreClass<VI>,
Action: IReduxActionConstructor<IData, VI>,
...reducer: ISingleReducer<VI, IData>[]) {
const vs = new Constructor;
return vs['reduceAny'](Action, ...reducer);
}
export function extractorOf<VI>(vs: IVirtualStoreClass<VI>) {
return function (state: IState): VI {
if (state[vs.name] === null || state[vs.name] === undefined) {
displayExtractError(state, vs.name);
}
return state[vs.name];
};
}
export function subExtractorOf<VI, KT = keyof VI>(vs: IVirtualStoreClass<VI>, key: KT) {
return function (state: IState) {
if (state[vs.name] === null || state[vs.name] === undefined) {
displayExtractError(state, vs.name);
}
if (!state[vs.name].hasOwnProperty(key)) {
displayExtractError(state, vs.name + '.' + key);
}
return state[vs.name][key];
};
}
const output = createLogger(LOG_LEVEL.ERROR, 'vs');
function displayExtractError(state: any, varName: string) {
output('================');
output(` Cannot get variable '${varName}' of redux store`);
output(` did you called store.reigster(${varName.replace(/\..*$/, '')})`);
output(` and defined a property "defaultValue" in subStore "${varName.replace(/\..*$/, '')}"`);
output(' STATE: %j', state);
output('================');
throw new Error(`Cannot get variable '${varName}' of redux store`);
}
export abstract class VirtualStore<ValueInterface> implements IVirtualStore<ValueInterface> {
private reducers: IReducerInfo<ValueInterface>[] = [];
readonly name: string;
readonly defaultValue: ValueInterface;
static readonly ANY = '*';
constructor() {
if (this.constructor['instance']) {
return this.constructor['instance'];
}
this.constructor['instance'] = this;
this.name = <any>this.constructor.name;
silly('construct vs: ', this.name)
}
protected reduce<IData extends IAData>(Action: IReduxActionConstructor<IData, ValueInterface>,
...reducer: ISingleReducer<ValueInterface, IData>[]): void {
for (let fn of reducer) {
this.reducers.push({
callback: fn,
actionName: Action.name,
storeName: this.name,
global: false,
});
}
}
protected reduceAny<IData extends IAData>(Action: IReduxActionConstructor<IData, any>,
...reducer: ISingleReducer<any, IData>[]): void {
for (let fn of reducer) {
this.reducers.push({
callback: fn,
actionName: Action.name,
storeName: this.name,
global: true,
});
}
}
public getReducers(): IReducerInfo<ValueInterface>[] {
Object.freeze(this.reducers);
return this.reducers;
}
}