UNPKG

3.68 kBPlain TextView Raw
1import {createLogger} from "@gongt/ts-stl-library/debug/create-logger";
2import {LOG_LEVEL} from "@gongt/ts-stl-library/debug/levels";
3import {IAData, IReduxActionConstructor, ISingleReducer} from "./action";
4import {IReducerInfo} from "./combine-reducers";
5import {IState} from "./preload-state";
6
7const silly = createLogger(LOG_LEVEL.SILLY, 'v-store');
8
9export interface IVirtualStore<ValueInterface> {
10 getReducers?(): IReducerInfo<ValueInterface>[];
11
12 name: string;
13 defaultValue?: ValueInterface;
14}
15
16export interface IVirtualStoreConstructor<ValueInterface> {
17 new(): IVirtualStore<ValueInterface>;
18
19 name: string;
20}
21
22/** only use in this file */
23export interface IVirtualStoreClass<ValueInterface> {
24 new(): VirtualStore<ValueInterface>;
25
26 name: string;
27}
28
29export function reduce<VI, IData extends IAData>
30(Constructor: IVirtualStoreClass<VI>,
31 Action: IReduxActionConstructor<IData, VI>,
32 ...reducer: ISingleReducer<VI, IData>[]) {
33 const vs = new Constructor;
34 return vs['reduce'](Action, ...reducer);
35}
36
37export function reduceAny<VI, IData extends IAData>
38(Constructor: IVirtualStoreClass<VI>,
39 Action: IReduxActionConstructor<IData, VI>,
40 ...reducer: ISingleReducer<VI, IData>[]) {
41 const vs = new Constructor;
42 return vs['reduceAny'](Action, ...reducer);
43}
44
45export function extractorOf<VI>(vs: IVirtualStoreClass<VI>) {
46 return function (state: IState): VI {
47 if (state[vs.name] === null || state[vs.name] === undefined) {
48 displayExtractError(state, vs.name);
49 }
50 return state[vs.name];
51 };
52}
53
54export function subExtractorOf<VI, KT = keyof VI>(vs: IVirtualStoreClass<VI>, key: KT) {
55 return function (state: IState) {
56 if (state[vs.name] === null || state[vs.name] === undefined) {
57 displayExtractError(state, vs.name);
58 }
59 if (!state[vs.name].hasOwnProperty(key)) {
60 displayExtractError(state, vs.name + '.' + key);
61 }
62 return state[vs.name][key];
63 };
64}
65
66const output = createLogger(LOG_LEVEL.ERROR, 'vs');
67
68function displayExtractError(state: any, varName: string) {
69 output('================');
70 output(` Cannot get variable '${varName}' of redux store`);
71 output(` did you called store.reigster(${varName.replace(/\..*$/, '')})`);
72 output(` and defined a property "defaultValue" in subStore "${varName.replace(/\..*$/, '')}"`);
73 output(' STATE: %j', state);
74 output('================');
75 throw new Error(`Cannot get variable '${varName}' of redux store`);
76}
77
78export abstract class VirtualStore<ValueInterface> implements IVirtualStore<ValueInterface> {
79 private reducers: IReducerInfo<ValueInterface>[] = [];
80 readonly name: string;
81 readonly defaultValue: ValueInterface;
82
83 static readonly ANY = '*';
84
85 constructor() {
86 if (this.constructor['instance']) {
87 return this.constructor['instance'];
88 }
89 this.constructor['instance'] = this;
90 this.name = <any>this.constructor.name;
91 silly('construct vs: ', this.name)
92 }
93
94 protected reduce<IData extends IAData>(Action: IReduxActionConstructor<IData, ValueInterface>,
95 ...reducer: ISingleReducer<ValueInterface, IData>[]): void {
96 for (let fn of reducer) {
97 this.reducers.push({
98 callback: fn,
99 actionName: Action.name,
100 storeName: this.name,
101 global: false,
102 });
103 }
104 }
105
106 protected reduceAny<IData extends IAData>(Action: IReduxActionConstructor<IData, any>,
107 ...reducer: ISingleReducer<any, IData>[]): void {
108 for (let fn of reducer) {
109 this.reducers.push({
110 callback: fn,
111 actionName: Action.name,
112 storeName: this.name,
113 global: true,
114 });
115 }
116 }
117
118 public getReducers(): IReducerInfo<ValueInterface>[] {
119 Object.freeze(this.reducers);
120 return this.reducers;
121 }
122}