fix(ngrx): add store typing

This adds the `<%= className%>PartialState` used to type the store from the
`DataPersistence` methods.
This adds the `XXX_FEATURE_KEY` to the `xxx.reducer.ts` file too.

close #748
This commit is contained in:
ben 2018-09-18 17:34:00 -04:00 committed by Victor Savkin
parent e63e787704
commit efe38c47a7
5 changed files with 17 additions and 11 deletions

View File

@ -2,13 +2,13 @@ import { Injectable } from '@angular/core';
import { Effect, Actions } from '@ngrx/effects'; import { Effect, Actions } from '@ngrx/effects';
import { DataPersistence } from '@nrwl/nx'; import { DataPersistence } from '@nrwl/nx';
import { <%= className %>State } from './<%= fileName %>.reducer'; import { <%= className %>PartialState } from './<%= fileName %>.reducer';
import { Load<%= className %>, <%= className %>Loaded, <%= className %>LoadError, <%= className %>ActionTypes } from './<%= fileName %>.actions'; import { Load<%= className %>, <%= className %>Loaded, <%= className %>LoadError, <%= className %>ActionTypes } from './<%= fileName %>.actions';
@Injectable() @Injectable()
export class <%= className %>Effects { export class <%= className %>Effects {
@Effect() load<%= className %>$ = this.dataPersistence.fetch(<%= className %>ActionTypes.Load<%= className %>, { @Effect() load<%= className %>$ = this.dataPersistence.fetch(<%= className %>ActionTypes.Load<%= className %>, {
run: (action: Load<%= className %>, state: <%= className %>State) => { run: (action: Load<%= className %>, state: <%= className %>PartialState) => {
// Your custom REST 'load' logic goes here. For now just return an empty list... // Your custom REST 'load' logic goes here. For now just return an empty list...
return new <%= className %>Loaded([]); return new <%= className %>Loaded([]);
}, },
@ -21,5 +21,5 @@ export class <%= className %>Effects {
constructor( constructor(
private actions$: Actions, private actions$: Actions,
private dataPersistence: DataPersistence<<%= className %>State>) { } private dataPersistence: DataPersistence<<%= className %>PartialState>) { }
} }

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { select, Store } from '@ngrx/store'; import { select, Store } from '@ngrx/store';
import { <%= className %>State } from './<%= fileName %>.reducer'; import { <%= className %>PartialState } from './<%= fileName %>.reducer';
import { <%= propertyName %>Query } from './<%= fileName %>.selectors'; import { <%= propertyName %>Query } from './<%= fileName %>.selectors';
import { Load<%= className %> } from './<%= fileName %>.actions'; import { Load<%= className %> } from './<%= fileName %>.actions';
@ -13,7 +13,7 @@ export class <%= className %>Facade {
all<%= className %>$ = this.store.pipe(select(<%= propertyName %>Query.getAll<%= className %>)); all<%= className %>$ = this.store.pipe(select(<%= propertyName %>Query.getAll<%= className %>));
selected<%= className %>$ = this.store.pipe(select(<%= propertyName %>Query.getSelected<%= className %>)); selected<%= className %>$ = this.store.pipe(select(<%= propertyName %>Query.getSelected<%= className %>));
constructor( private store: Store<{<%= propertyName %>: <%= className %>State}> ) { } constructor(private store: Store<<%= className %>PartialState>) { }
loadAll() { loadAll() {
this.store.dispatch(new Load<%= className %>()); this.store.dispatch(new Load<%= className %>());

View File

@ -1,5 +1,7 @@
import { <%= className %>Action, <%= className %>ActionTypes } from './<%= fileName %>.actions'; import { <%= className %>Action, <%= className %>ActionTypes } from './<%= fileName %>.actions';
export const <%= className.toUpperCase() %>_FEATURE_KEY = '<%= propertyName %>';
/** /**
* Interface for the '<%= className %>' data used in * Interface for the '<%= className %>' data used in
* - <%= className %>State, and * - <%= className %>State, and
@ -19,6 +21,10 @@ export interface <%= className %>State {
error ?: any; // last none error (if any) error ?: any; // last none error (if any)
}; };
export interface <%= className %>PartialState {
readonly [<%= className.toUpperCase() %>_FEATURE_KEY]: <%= className %>State;
}
export const initialState: <%= className %>State = { export const initialState: <%= className %>State = {
list : [ ], list : [ ],
loaded : false loaded : false

View File

@ -166,7 +166,7 @@ describe('ngrx', () => {
const appModule = getFileContent(tree, '/apps/myapp/src/app/app.module.ts'); const appModule = getFileContent(tree, '/apps/myapp/src/app/app.module.ts');
expect(appModule).toContain('StoreModule.forFeature'); expect(appModule).toContain('StoreModule.forFeature');
expect(appModule).toContain('EffectsModule.forFeature'); expect(appModule).toContain('EffectsModule.forFeature');
expect(appModule).toContain("'state', stateReducer"); expect(appModule).toContain('STATE_FEATURE_KEY, stateReducer');
expect(appModule).toContain('{ initialState: stateInitialState }'); expect(appModule).toContain('{ initialState: stateInitialState }');
expect(appModule).not.toContain( expect(appModule).not.toContain(
'!environment.production ? [storeFreeze] : []' '!environment.production ? [storeFreeze] : []'
@ -357,7 +357,7 @@ describe('ngrx', () => {
const content = getFileContent(tree, `${statePath}/users.facade.ts`); const content = getFileContent(tree, `${statePath}/users.facade.ts`);
[ [
`import { UsersState } from './users.reducer'`, `import { UsersPartialState } from './users.reducer'`,
`import { usersQuery } from './users.selectors'`, `import { usersQuery } from './users.selectors'`,
`export class UsersFacade` `export class UsersFacade`
].forEach(text => { ].forEach(text => {
@ -397,11 +397,11 @@ describe('ngrx', () => {
`import { DataPersistence } from \'@nrwl/nx\'`, `import { DataPersistence } from \'@nrwl/nx\'`,
`import { LoadUsers, UsersLoaded, UsersLoadError, UsersActionTypes } from \'./users.actions\'`, `import { LoadUsers, UsersLoaded, UsersLoadError, UsersActionTypes } from \'./users.actions\'`,
`loadUsers$`, `loadUsers$`,
`run: (action: LoadUsers, state: UsersState)`, `run: (action: LoadUsers, state: UsersPartialState)`,
`return new UsersLoaded([])`, `return new UsersLoaded([])`,
`return new UsersLoadError(error)`, `return new UsersLoadError(error)`,
'private actions$: Actions', 'private actions$: Actions',
'private dataPersistence: DataPersistence<UsersState>)' 'private dataPersistence: DataPersistence<UsersPartialState>)'
].forEach(text => { ].forEach(text => {
expect(content).toContain(text); expect(content).toContain(text);
}); });

View File

@ -38,7 +38,7 @@ export function addImportsToModule(context: RequestContext): Rule {
const reducerName = `${toPropertyName(context.featureName)}Reducer`; const reducerName = `${toPropertyName(context.featureName)}Reducer`;
const effectsName = `${toClassName(context.featureName)}Effects`; const effectsName = `${toClassName(context.featureName)}Effects`;
const facadeName = `${toClassName(context.featureName)}Facade`; const facadeName = `${toClassName(context.featureName)}Facade`;
const reducerImports = `initialState as ${featureName}InitialState, ${reducerName}`; const reducerImports = `${featureName.toUpperCase()}_FEATURE_KEY, initialState as ${featureName}InitialState, ${reducerName}`;
const storeReducers = `{ ${featureName}: ${reducerName} }`; const storeReducers = `{ ${featureName}: ${reducerName} }`;
const storeInitState = `initialState : { ${featureName} : ${featureName}InitialState }`; const storeInitState = `initialState : { ${featureName} : ${featureName}InitialState }`;
@ -55,7 +55,7 @@ export function addImportsToModule(context: RequestContext): Rule {
const storeForEmptyRoot = `StoreModule.forRoot({},{ ${storeMetaReducers} })`; const storeForEmptyRoot = `StoreModule.forRoot({},{ ${storeMetaReducers} })`;
const effectsForRoot = `EffectsModule.forRoot([${effectsName}])`; const effectsForRoot = `EffectsModule.forRoot([${effectsName}])`;
const effectsForEmptyRoot = `EffectsModule.forRoot([])`; const effectsForEmptyRoot = `EffectsModule.forRoot([])`;
const storeForFeature = `StoreModule.forFeature('${featureName}', ${reducerName}, { initialState: ${featureName}InitialState })`; const storeForFeature = `StoreModule.forFeature(${featureName.toUpperCase()}_FEATURE_KEY, ${reducerName}, { initialState: ${featureName}InitialState })`;
const effectsForFeature = `EffectsModule.forFeature([${effectsName}])`; const effectsForFeature = `EffectsModule.forFeature([${effectsName}])`;
const devTools = `!environment.production ? StoreDevtoolsModule.instrument() : []`; const devTools = `!environment.production ? StoreDevtoolsModule.instrument() : []`;
const storeRouterModule = 'StoreRouterConnectingModule'; const storeRouterModule = 'StoreRouterConnectingModule';