in packages/redux-dynamic-modules-core/src/Managers/ModuleManager.ts [20:188]
export function getModuleManager<State = {}>(
middlewareManager: IItemManager<Middleware>,
extensions: IExtension[],
advancedCombineReducers?: (
reducers: ReducersMapObject<State, any>
) => Reducer<State>
): IModuleManager<State> {
let _dispatch = null;
let _reducerManager: IReducerManager<State>;
let _modules: IModule<any>[] = [];
const _moduleIds = new Set();
const _seedReducers = () => {
_dispatch({ type: "@@Internal/ModuleManager/SeedReducers" });
};
const _dispatchActions = (actions: AnyAction[]) => {
if (!actions) {
return;
}
if (!_dispatch) {
throw new Error(
"setDispatch should be called on ModuleManager before adding any modules."
);
}
actions.forEach(_dispatch);
};
const _addMiddlewares = (middlewares: Middleware[]) => {
if (!middlewares) {
return;
}
middlewareManager.add(middlewares);
};
const _removeMiddlewares = (middlewares: Middleware[]) => {
if (!middlewares) {
return;
}
middlewareManager.remove(middlewares);
};
const _addReducers = (
reducerMap: ReducersMapObject<Reducer, AnyAction>
) => {
if (!reducerMap) {
return;
}
if (!_reducerManager) {
_reducerManager = getRefCountedReducerManager(
// @ts-ignore
getReducerManager(reducerMap, advancedCombineReducers)
) as any;
} else {
for (const key in reducerMap) {
_reducerManager.add(key, reducerMap[key]);
}
}
};
const _removeReducers = (
reducerMap: ReducersMapObject<Reducer, AnyAction>
) => {
if (!reducerMap || !_reducerManager) {
return;
}
for (const key in reducerMap) {
_reducerManager.remove(key);
}
};
// Create reduce function which redirects to _reducers.reduce
const _reduce = (s: State, a: AnyAction) => {
if (_reducerManager) {
return _reducerManager.reduce(s, a);
}
return s || null;
};
const moduleManager = {
getReducer: _reduce,
setDispatch: (dispatch: Dispatch<AnyAction>) => {
_dispatch = dispatch;
},
getItems: () => [], //We are not keeping a copy of added modules, for now no one calls this so we are ok
add: (modulesToAdd: IModule<any>[]) => {
if (!modulesToAdd || modulesToAdd.length === 0) {
return;
}
modulesToAdd = modulesToAdd.filter(module => module);
const justAddedModules: IModule<any>[] = [];
modulesToAdd.forEach(module => {
if (!_moduleIds.has(module.id)) {
_moduleIds.add(module.id);
_modules.push(module);
_addReducers(module.reducerMap);
const middlewares = module.middlewares;
if (middlewares) {
_addMiddlewares(middlewares);
}
justAddedModules.push(module);
}
});
/* Fire an action so that the newly added reducers can seed their initial state */
_seedReducers();
// add the sagas and dispatch actions at the end so all the reducers are registered
justAddedModules.forEach(module => {
// Let the extensions know we added a module
extensions.forEach(p => {
if (p.onModuleAdded) {
p.onModuleAdded(module);
}
});
// Dispatch the initial actions
const moduleAddedAction = {
type: "@@Internal/ModuleManager/ModuleAdded",
payload: module.id,
};
_dispatchActions(
module.initialActions
? [moduleAddedAction, ...module.initialActions]
: [moduleAddedAction]
);
});
},
remove: (modulesToRemove: IModule<any>[]) => {
if (!modulesToRemove) {
return;
}
modulesToRemove = modulesToRemove
.filter(module => module)
.reverse();
modulesToRemove.forEach(module => {
if (_moduleIds.has(module.id)) {
_dispatchActions(module.finalActions);
_removeReducers(module.reducerMap);
_removeMiddlewares(module.middlewares);
// Let the extensions know we removed a module
extensions.forEach(p => {
if (p.onModuleRemoved) {
p.onModuleRemoved(module);
}
});
_moduleIds.delete(module.id);
_modules = _modules.filter(m => m.id !== module.id);
_dispatchActions([
{
type: "@@Internal/ModuleManager/ModuleRemoved",
payload: module.id,
},
]);
}
});
},
dispose: () => {
moduleManager.remove(_modules);
},
};
return moduleManager;
}