UNPKG

@gongt/ts-stl-client

Version:
123 lines (103 loc) 3.68 kB
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; } }