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 { getReducers?(): IReducerInfo[]; name: string; defaultValue?: ValueInterface; } export interface IVirtualStoreConstructor { new(): IVirtualStore; name: string; } /** only use in this file */ export interface IVirtualStoreClass { new(): VirtualStore; name: string; } export function reduce (Constructor: IVirtualStoreClass, Action: IReduxActionConstructor, ...reducer: ISingleReducer[]) { const vs = new Constructor; return vs['reduce'](Action, ...reducer); } export function reduceAny (Constructor: IVirtualStoreClass, Action: IReduxActionConstructor, ...reducer: ISingleReducer[]) { const vs = new Constructor; return vs['reduceAny'](Action, ...reducer); } export function extractorOf(vs: IVirtualStoreClass) { 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(vs: IVirtualStoreClass, 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 implements IVirtualStore { private reducers: IReducerInfo[] = []; readonly name: string; readonly defaultValue: ValueInterface; static readonly ANY = '*'; constructor() { if (this.constructor['instance']) { return this.constructor['instance']; } this.constructor['instance'] = this; this.name = this.constructor.name; silly('construct vs: ', this.name) } protected reduce(Action: IReduxActionConstructor, ...reducer: ISingleReducer[]): void { for (let fn of reducer) { this.reducers.push({ callback: fn, actionName: Action.name, storeName: this.name, global: false, }); } } protected reduceAny(Action: IReduxActionConstructor, ...reducer: ISingleReducer[]): void { for (let fn of reducer) { this.reducers.push({ callback: fn, actionName: Action.name, storeName: this.name, global: true, }); } } public getReducers(): IReducerInfo[] { Object.freeze(this.reducers); return this.reducers; } }