Skip to content

Commit

Permalink
feat(usealien): receive and array of alienModules instead of a single…
Browse files Browse the repository at this point in the history
… module

this allow register multiple modules is some of then depend of some one

#43
  • Loading branch information
aneurysmjs committed Jan 13, 2020
1 parent d25f368 commit 98d2142
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 22 deletions.
10 changes: 5 additions & 5 deletions src/app/store/config/alienStore/useAlien.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('useAlien', () => {
getModule: (): ReduxModuleType => Promise.resolve(reduxModule),
};

const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), {
const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
});

Expand All @@ -59,7 +59,7 @@ describe('useAlien', () => {

const cb = jest.fn();

const { result, waitForNextUpdate, unmount } = renderHook(() => useAlien(alienModule, cb), {
const { result, waitForNextUpdate, unmount } = renderHook(() => useAlien([alienModule], cb), {
wrapper,
});

Expand Down Expand Up @@ -88,7 +88,7 @@ describe('useAlien', () => {
};

// @ts-ignore - "id" doesn't exist for testing purposes
const { result } = renderHook(() => useAlien(alienModule), {
const { result } = renderHook(() => useAlien([alienModule]), {
wrapper,
});

Expand All @@ -107,7 +107,7 @@ describe('useAlien', () => {
getModule: (): ReduxModuleType => import(WRONG_COMPONENT_PATH),
};

const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), {
const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
});

Expand All @@ -132,7 +132,7 @@ describe('useAlien', () => {
getModule: (): ReduxModuleNoReducersType => Promise.resolve(reduxModuleNoReducers),
};

const { result, waitForNextUpdate } = renderHook(() => useAlien(alienModule), {
const { result, waitForNextUpdate } = renderHook(() => useAlien([alienModule]), {
wrapper,
});

Expand Down
40 changes: 25 additions & 15 deletions src/app/store/config/alienStore/useAlien.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { Reducer, AnyAction, ActionCreator } from 'redux';
import { useStore } from 'react-redux';
import { isEmpty, isNil } from 'ramda';
import { isEmpty, isNil, anyPass, any } from 'ramda';

import { AlienStore } from './alien';

Expand All @@ -13,7 +13,7 @@ export interface ReduxModule<T = {}> {
[K: string]: ActionCreator<AnyAction>;
};
selectors?: {
[K: string]: <S>(state: S) => T;
[K: string]: <T>(state: T) => T;
};
}

Expand All @@ -25,6 +25,8 @@ export interface AlienModule<T = {}> {
initialActions?: Array<string>;
}

const check: <T>(obj: T) => boolean = anyPass([isNil, isEmpty]);

function errorHandler<T>(errorOrObj: T): T {
if (errorOrObj) {
// rejection from `import()` for some reason is not and instance of Error
Expand All @@ -36,8 +38,11 @@ function errorHandler<T>(errorOrObj: T): T {
return errorOrObj;
}

// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function useAlien<T>(alienModule: AlienModule<T>, cb: () => void = () => {}): AlienResult | null {
function useAlien<T>(
alienModules: [AlienModule<T>],
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
cb: () => void = () => {},
): AlienResult | null {
const store = useStore() as AlienStore;
const {
alienManager: { injectReducers, rootReducer },
Expand All @@ -47,23 +52,28 @@ function useAlien<T>(alienModule: AlienModule<T>, cb: () => void = () => {}): Al
useEffect(() => {
(async (): Promise<void> => {
try {
if (isNil(alienModule.id) || isEmpty(alienModule.id)) {
if (any(({ id }) => check(id), alienModules)) {
throw new Error('Alien Module has no id');
}
const promises = alienModules.map(alienModule => alienModule.getModule());

const { reducers, actions, selectors } = await alienModule.getModule();
const resolvedModules = await Promise.all(promises);

if (isNil(reducers) || isEmpty(reducers)) {
throw new Error('Redux Module has no reducers');
}
// is safe here to iterate reducers's keys for reducer injection
Object.keys(reducers).forEach(key => {
injectReducers(key, reducers[key]);
});
resolvedModules.forEach(alienModule => {
const { reducers, actions, selectors } = alienModule;

store.replaceReducer(rootReducer);
if (check(reducers)) {
throw new Error('Redux Module has no reducers');
}
// is safe here to iterate reducers's keys for reducer injection
Object.keys(reducers).forEach(key => {
injectReducers(key, reducers[key]);
});

setAlien({ actions, selectors });
store.replaceReducer(rootReducer);

setAlien({ actions, selectors });
});
} catch (err) {
setAlien(err);
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/store/config/alienStore/withAlien.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('test "withAlien"', () => {
id: 'with',
getModule,
};
const { result, waitForNextUpdate } = renderHook(() => withAlien(Example, alienModule), {
const { result, waitForNextUpdate } = renderHook(() => withAlien(Example, [alienModule]), {
wrapper,
});

Expand Down
2 changes: 1 addition & 1 deletion src/app/store/config/alienStore/withAlien.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface WithAlienProps {

function WithAlien<P extends object>(
Component: ComponentType<P>,
alienModule: AlienModule,
alienModule: [AlienModule],
): ReactElement<P & WithAlienProps> | null {
const alienResult = useAlien(alienModule);

Expand Down

0 comments on commit 98d2142

Please sign in to comment.