1 | import {createLogger} from "@gongt/ts-stl-library/debug/create-logger";
|
2 | import {LOG_LEVEL} from "@gongt/ts-stl-library/debug/levels";
|
3 | import {IAData, IReduxActionConstructor, ISingleReducer} from "./action";
|
4 | import {IReducerInfo} from "./combine-reducers";
|
5 | import {IState} from "./preload-state";
|
6 |
|
7 | const silly = createLogger(LOG_LEVEL.SILLY, 'v-store');
|
8 |
|
9 | export interface IVirtualStore<ValueInterface> {
|
10 | getReducers?(): IReducerInfo<ValueInterface>[];
|
11 |
|
12 | name: string;
|
13 | defaultValue?: ValueInterface;
|
14 | }
|
15 |
|
16 | export interface IVirtualStoreConstructor<ValueInterface> {
|
17 | new(): IVirtualStore<ValueInterface>;
|
18 |
|
19 | name: string;
|
20 | }
|
21 |
|
22 |
|
23 | export interface IVirtualStoreClass<ValueInterface> {
|
24 | new(): VirtualStore<ValueInterface>;
|
25 |
|
26 | name: string;
|
27 | }
|
28 |
|
29 | export 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 |
|
37 | export 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 |
|
45 | export 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 |
|
54 | export 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 |
|
66 | const output = createLogger(LOG_LEVEL.ERROR, 'vs');
|
67 |
|
68 | function 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 |
|
78 | export 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 | }
|