Skip to content

Commit

Permalink
feat(auth): add injectable reducers (#2454)
Browse files Browse the repository at this point in the history
* feat(auth): add injectable reducers

* feat(auth): export individual selector factories

* use reducers from token
  • Loading branch information
griest024 committed May 24, 2023
1 parent 9afcabd commit c0fc259
Show file tree
Hide file tree
Showing 19 changed files with 203 additions and 31 deletions.
8 changes: 3 additions & 5 deletions libs/auth/state/src/auth-state.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ import { DaffAuthEffects } from './effects/auth.effects';
import { DaffAuthLoginEffects } from './effects/login.effects';
import { DaffAuthRegisterEffects } from './effects/register.effects';
import { DaffAuthResetPasswordEffects } from './effects/reset-password.effects';
import {
DAFF_AUTH_STORE_FEATURE_KEY,
daffAuthReducers,
} from './reducers/public_api';
import { DAFF_AUTH_STORE_FEATURE_KEY } from './reducers/public_api';
import { DAFF_AUTH_REDUCERS } from './reducers/token/reducers.token';

@NgModule({
imports: [
StoreModule.forFeature(DAFF_AUTH_STORE_FEATURE_KEY, daffAuthReducers),
StoreModule.forFeature(DAFF_AUTH_STORE_FEATURE_KEY, DAFF_AUTH_REDUCERS),
EffectsModule.forFeature([
DaffAuthEffects,
DaffAuthLoginEffects,
Expand Down
4 changes: 2 additions & 2 deletions libs/auth/state/src/facades/auth/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Observable } from 'rxjs';
import { DaffStateError } from '@daffodil/core/state';

import { DaffAuthStateRootSlice } from '../../reducers/public_api';
import { getAuthSelectors } from '../../selectors/auth/auth.selector';
import { daffAuthSelectorFactory } from '../../selectors/auth/auth.selector';
import { DaffAuthFacadeInterface } from './facade.interface';

/**
Expand All @@ -28,7 +28,7 @@ export class DaffAuthFacade implements DaffAuthFacadeInterface {
selectLoading,
selectErrors,
selectAuthLoggedIn,
} = getAuthSelectors();
} = daffAuthSelectorFactory();

this.loading$ = this.store.pipe(select(selectLoading));
this.errors$ = this.store.pipe(select(selectErrors));
Expand Down
4 changes: 2 additions & 2 deletions libs/auth/state/src/facades/login/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Observable } from 'rxjs';
import { DaffStateError } from '@daffodil/core/state';

import { DaffAuthStateRootSlice } from '../../reducers/public_api';
import { getDaffAuthLoginSelectors } from '../../selectors/login/login.selector';
import { daffAuthLoginSelectorFactory } from '../../selectors/login/login.selector';
import { DaffAuthLoginFacadeInterface } from './facade.interface';

/**
Expand All @@ -26,7 +26,7 @@ export class DaffAuthLoginFacade implements DaffAuthLoginFacadeInterface {
const {
selectLoading,
selectErrors,
} = getDaffAuthLoginSelectors();
} = daffAuthLoginSelectorFactory();

this.loading$ = this.store.pipe(select(selectLoading));
this.errors$ = this.store.pipe(select(selectErrors));
Expand Down
4 changes: 2 additions & 2 deletions libs/auth/state/src/facades/register/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Observable } from 'rxjs';
import { DaffStateError } from '@daffodil/core/state';

import { DaffAuthStateRootSlice } from '../../reducers/public_api';
import { getDaffAuthRegisterSelectors } from '../../selectors/register/register.selector';
import { daffAuthRegisterSelectorFactory } from '../../selectors/register/register.selector';
import { DaffAuthRegisterFacadeInterface } from './facade.interface';

/**
Expand All @@ -26,7 +26,7 @@ export class DaffAuthRegisterFacade implements DaffAuthRegisterFacadeInterface {
const {
selectLoading,
selectErrors,
} = getDaffAuthRegisterSelectors();
} = daffAuthRegisterSelectorFactory();

this.loading$ = this.store.pipe(select(selectLoading));
this.errors$ = this.store.pipe(select(selectErrors));
Expand Down
4 changes: 2 additions & 2 deletions libs/auth/state/src/facades/reset-password/facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DaffAuthResetPasswordInfo } from '@daffodil/auth';
import { DaffStateError } from '@daffodil/core/state';

import { DaffAuthStateRootSlice } from '../../reducers/public_api';
import { getDaffAuthResetPasswordSelectors } from '../../selectors/reset-password/selector';
import { daffAuthResetPasswordSelectorFactory } from '../../selectors/reset-password/selector';
import { DaffAuthResetPasswordFacadeInterface } from './facade.interface';

/**
Expand All @@ -30,7 +30,7 @@ export class DaffAuthResetPasswordFacade implements DaffAuthResetPasswordFacadeI
selectLoading,
selectErrors,
selectAuthResetPasswordToken,
} = getDaffAuthResetPasswordSelectors();
} = daffAuthResetPasswordSelectorFactory();

this.token$ = this.store.pipe(select(selectAuthResetPasswordToken));

Expand Down
1 change: 1 addition & 0 deletions libs/auth/state/src/reducers/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './auth/public_api';
export * from './login/public_api';
export * from './register/public_api';
export * from './reset-password/public_api';
export * from './token/public_api';

export { DAFF_AUTH_STORE_FEATURE_KEY } from './auth-store-feature-key';
export { daffAuthReducers } from './auth-reducers';
Expand Down
35 changes: 35 additions & 0 deletions libs/auth/state/src/reducers/token/extra.token.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { TestBed } from '@angular/core/testing';
import { ActionReducer } from '@ngrx/store';

import { DaffAuthFeatureState } from '@daffodil/auth/state';

import {
daffAuthProvideExtraReducers,
DAFF_AUTH_EXTRA_REDUCERS,
} from './extra.token';

describe('daffAuthProvideExtraReducers', () => {
let reducers: ActionReducer<DaffAuthFeatureState>[];
let result: ActionReducer<DaffAuthFeatureState>[];

beforeEach(() => {
reducers = [
(state, action) => state,
(state, action) => state,
];

TestBed.configureTestingModule({
providers: [
...daffAuthProvideExtraReducers(...reducers),
],
});

result = TestBed.inject(DAFF_AUTH_EXTRA_REDUCERS);
});

it('should provide the reducers to the token', () => {
reducers.forEach(reducer => {
expect(result).toContain(reducer);
});
});
});
39 changes: 39 additions & 0 deletions libs/auth/state/src/reducers/token/extra.token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
InjectionToken,
Provider,
} from '@angular/core';
import { ActionReducer } from '@ngrx/store';

import { DaffAuthFeatureState } from '../auth-feature-state.interface';

/**
* A token to hold the injectable extra reducers.
*
* Prefer using {@link daffAuthProvideExtraReducers}.
*/
export const DAFF_AUTH_EXTRA_REDUCERS = new InjectionToken<ActionReducer<DaffAuthFeatureState>[]>(
'DAFF_AUTH_EXTRA_REDUCERS',
{ factory: () => []},
);

/**
* Provides additional reducers that run after the standard Daffodil auth reducers.
*
* ```ts
* providers: [
* ...daffAuthProvideExtraReducers(
* myReducer1,
* myReducer2
* )
* ]
* ```
*/
export function daffAuthProvideExtraReducers(
...reducers: ActionReducer<DaffAuthFeatureState>[]
): Provider[] {
return reducers.map(reducer => ({
provide: DAFF_AUTH_EXTRA_REDUCERS,
useValue: reducer,
multi: true,
}));
}
4 changes: 4 additions & 0 deletions libs/auth/state/src/reducers/token/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export {
daffAuthProvideExtraReducers,
DAFF_AUTH_EXTRA_REDUCERS,
} from './extra.token';
61 changes: 61 additions & 0 deletions libs/auth/state/src/reducers/token/reducers.token.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { TestBed } from '@angular/core/testing';
import { ActionReducer } from '@ngrx/store';

import {
DaffAuthFeatureState,
daffAuthInitialState,
DaffAuthCheck,
} from '@daffodil/auth/state';
import { DaffStateError } from '@daffodil/core/state';

import { daffAuthProvideExtraReducers } from './extra.token';
import { DAFF_AUTH_REDUCERS } from './reducers.token';

describe('daffAuthProvideExtraReducers', () => {
let extraReducer: ActionReducer<DaffAuthFeatureState>;
let reducer: ActionReducer<DaffAuthFeatureState>;
let result: DaffAuthFeatureState;
let error: DaffStateError;

beforeEach(() => {
error = {
code: 'code',
message: 'message',
};
const initialState: DaffAuthFeatureState = {
auth: {
...daffAuthInitialState,
daffErrors: [
{ code: '0', message: '0' },
],
},
login: null,
register: null,
resetPassword: null,
};
extraReducer = (state, action) => ({
...state,
auth: {
...state.auth,
daffErrors: [
...state.auth.daffErrors,
error,
],
},
});

TestBed.configureTestingModule({
providers: [
...daffAuthProvideExtraReducers(extraReducer),
],
});

reducer = TestBed.inject(DAFF_AUTH_REDUCERS);

result = reducer(initialState, new DaffAuthCheck());
});

it('should run the extra reducer after the daffodil reducers', () => {
expect(result.auth.daffErrors[1]).toEqual(error);
});
});
30 changes: 30 additions & 0 deletions libs/auth/state/src/reducers/token/reducers.token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
inject,
InjectionToken,
} from '@angular/core';
import {
ActionReducer,
combineReducers,
} from '@ngrx/store';

import { daffComposeReducers } from '@daffodil/core/state';

import { DaffAuthFeatureState } from '../auth-feature-state.interface';
import { daffAuthReducers } from '../auth-reducers';
import { DAFF_AUTH_EXTRA_REDUCERS } from './extra.token';

/**
* An internal token to hold the Daffodil auth reducers.
* Includes the extra and standard reducers.
*
* @docs-private
*/
export const DAFF_AUTH_REDUCERS = new InjectionToken<ActionReducer<DaffAuthFeatureState>>(
'DAFF_AUTH_REDUCERS',
{
factory: () => daffComposeReducers([
combineReducers(daffAuthReducers),
...inject(DAFF_AUTH_EXTRA_REDUCERS),
]),
},
);
16 changes: 8 additions & 8 deletions libs/auth/state/src/selectors/auth-all.selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { MemoizedSelector } from '@ngrx/store';
import { DaffAuthFeatureState } from '../reducers/public_api';
import { getDaffAuthFeatureStateSelector } from './auth-feature.selector';
import {
getAuthSelectors,
daffAuthSelectorFactory,
AuthSelectors,
} from './auth/auth.selector';
import {
getDaffAuthLoginSelectors,
daffAuthLoginSelectorFactory,
DaffAuthLoginSelectors,
} from './login/login.selector';
import {
getDaffAuthRegisterSelectors,
daffAuthRegisterSelectorFactory,
DaffAuthRegisterSelectors,
} from './register/register.selector';
import {
DaffAuthResetPasswordSelectors,
getDaffAuthResetPasswordSelectors,
daffAuthResetPasswordSelectorFactory,
} from './reset-password/selector';

export interface DaffAuthSelectors extends
Expand All @@ -31,10 +31,10 @@ export const getDaffAuthSelectors = (() => {
let cache;
return (): DaffAuthSelectors =>
cache = cache || {
...getAuthSelectors(),
...getDaffAuthLoginSelectors(),
...getDaffAuthRegisterSelectors(),
...getDaffAuthResetPasswordSelectors(),
...daffAuthSelectorFactory(),
...daffAuthLoginSelectorFactory(),
...daffAuthRegisterSelectorFactory(),
...daffAuthResetPasswordSelectorFactory(),
selectAuthFeatureState: getDaffAuthFeatureStateSelector(),
};
})();
6 changes: 3 additions & 3 deletions libs/auth/state/src/selectors/auth/auth.selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import {
} from '@daffodil/auth/state';
import { DaffStateError } from '@daffodil/core/state';

import { getAuthSelectors } from './auth.selector';
import { daffAuthSelectorFactory } from './auth.selector';

describe('@daffodil/auth/state | getAuthSelectors', () => {
describe('@daffodil/auth/state | daffAuthSelectorFactory', () => {
let store: Store<DaffAuthStateRootSlice>;

let state: DaffAuthReducerState;
Expand All @@ -29,7 +29,7 @@ describe('@daffodil/auth/state | getAuthSelectors', () => {
const {
selectAuthState,
selectAuthLoggedIn,
} = getAuthSelectors();
} = daffAuthSelectorFactory();

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
2 changes: 1 addition & 1 deletion libs/auth/state/src/selectors/auth/auth.selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const createAuthSelectors = () => {
};
};

export const getAuthSelectors = (() => {
export const daffAuthSelectorFactory = (() => {
let cache;
return (): AuthSelectors =>
cache = cache || createAuthSelectors();
Expand Down
2 changes: 1 addition & 1 deletion libs/auth/state/src/selectors/login/login.selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const createLoginSelectors = () => {
};
};

export const getDaffAuthLoginSelectors = (() => {
export const daffAuthLoginSelectorFactory = (() => {
let cache;
return (): DaffAuthLoginSelectors =>
cache = cache || createLoginSelectors();
Expand Down
4 changes: 4 additions & 0 deletions libs/auth/state/src/selectors/public_api.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export * from './auth-all.selector';
export * from './auth/auth.selector';
export * from './login/login.selector';
export * from './register/register.selector';
export * from './reset-password/selector';
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const createRegisterSelectors = () => {
};
};

export const getDaffAuthRegisterSelectors = (() => {
export const daffAuthRegisterSelectorFactory = (() => {
let cache;
return (): DaffAuthRegisterSelectors =>
cache = cache || createRegisterSelectors();
Expand Down
6 changes: 3 additions & 3 deletions libs/auth/state/src/selectors/reset-password/selector.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {
DaffResetPasswordLanding,
daffAuthResetPasswordInitialState,
} from '../../public_api';
import { getDaffAuthResetPasswordSelectors } from './selector';
import { daffAuthResetPasswordSelectorFactory } from './selector';

describe('@daffodil/auth/state | getDaffAuthResetPasswordSelectors', () => {
describe('@daffodil/auth/state | daffAuthResetPasswordSelectorFactory', () => {
let store: Store<DaffAuthStateRootSlice>;

let state: DaffAuthResetPasswordReducerState;
Expand All @@ -32,7 +32,7 @@ describe('@daffodil/auth/state | getDaffAuthResetPasswordSelectors', () => {
const {
selectAuthResetPasswordState,
selectAuthResetPasswordToken,
} = getDaffAuthResetPasswordSelectors();
} = daffAuthResetPasswordSelectorFactory();

beforeEach(() => {
TestBed.configureTestingModule({
Expand Down
2 changes: 1 addition & 1 deletion libs/auth/state/src/selectors/reset-password/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const createResetPasswordSelectors = (): DaffAuthResetPasswordSelectors => {
};
};

export const getDaffAuthResetPasswordSelectors = (() => {
export const daffAuthResetPasswordSelectorFactory = (() => {
let cache;
return (): DaffAuthResetPasswordSelectors =>
cache = cache || createResetPasswordSelectors();
Expand Down

0 comments on commit c0fc259

Please sign in to comment.