89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
import { List, Map } from 'immutable';
|
|
import { RequestType } from './types';
|
|
import { request, success, failure } from '../tools'; //
|
|
|
|
export const ROOT_KEY = '_';
|
|
const defaultReducer = (state = Map()) => state;
|
|
|
|
|
|
const simpleRequestInitialState = Map({
|
|
loading: false,
|
|
errors: null,
|
|
});
|
|
|
|
const getKeys = types => Object.keys(types).filter(key => key !== ROOT_KEY);
|
|
|
|
export function getRequestInitialState(types) {
|
|
if (typeof types === 'string' || Array.isArray(types)) {
|
|
return simpleRequestInitialState;
|
|
}
|
|
let initialState = Map();
|
|
if (types[ ROOT_KEY ]) {
|
|
initialState = getRequestInitialState(types[ ROOT_KEY ]);
|
|
}
|
|
return getKeys(types).reduce(
|
|
(accumState, key) => accumState.set(key, getRequestInitialState(types[ key ])),
|
|
initialState,
|
|
);
|
|
}
|
|
|
|
function createSimpleRequestReducer(types, reducer) {
|
|
const typesArray = Array.isArray(types) ? types : [ types ];
|
|
const requestEvents = typesArray.map(t => t.request || request(t)); // back compat.
|
|
const successEvents = typesArray.map(t => t.success || success(t));
|
|
const failureEvents = typesArray.map(t => t.failure || failure(t));
|
|
|
|
let loadingCounter = 0;
|
|
|
|
return (state, action = {}) => {
|
|
if (state === undefined) {
|
|
if (typeof reducer === "function") { // flow?
|
|
state = reducer(state, action).merge(simpleRequestInitialState);
|
|
} else {
|
|
state = simpleRequestInitialState;
|
|
}
|
|
}
|
|
if (requestEvents.includes(action.type)) {
|
|
loadingCounter += 1;
|
|
return state.set('loading', loadingCounter > 0).set('errors', null);
|
|
}
|
|
if (successEvents.includes(action.type)) {
|
|
loadingCounter -= 1;
|
|
return state.set('loading', loadingCounter > 0).set('errors', null);
|
|
}
|
|
if (failureEvents.includes(action.type)) {
|
|
loadingCounter -= 1;
|
|
return state.set('loading', loadingCounter > 0).set('errors', List(action.errors));
|
|
}
|
|
return state;
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @types: RequestTypes - array or single
|
|
* or object like {'state1': RequestTypes, 'state2': [RequestTypes] ... }
|
|
* */
|
|
export function createRequestReducer(types, reducer = defaultReducer) {
|
|
if (typeof types === 'string' || types instanceof RequestType || Array.isArray(types)) {
|
|
return createSimpleRequestReducer(types);
|
|
}
|
|
|
|
const keys = getKeys(types);
|
|
const reducers = {};
|
|
keys.map((key) => { reducers[ key ] = createRequestReducer(types[ key ]); });
|
|
|
|
let rootReducer = typeof reducer === 'function' ? reducer : defaultReducer;
|
|
// TODO: remove ROOT_KEY logic
|
|
if (types[ ROOT_KEY ]) {
|
|
rootReducer = createRequestReducer(types[ ROOT_KEY ], rootReducer);
|
|
}
|
|
return (state, action = {}) => {
|
|
state = rootReducer(state, action);
|
|
keys.map((key) => {
|
|
state = state.update(key, subState => reducers[ key ](subState, action));
|
|
});
|
|
return state;
|
|
};
|
|
};
|
|
|
|
|