diff --git a/package.json b/package.json index 6e9c295286..d2c113b2c3 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@ngrx/store": "4.0.3", "@ngrx/router-store": "4.0.3", "@ngrx/effects": "4.0.3", + "@ngrx/store-devtools": "^4.0.0", "typescript": "2.4.2", "@types/node": "8.0.7", "@types/jasmine": "2.5.53", diff --git a/packages/schematics/src/ngrx/files/+state/__fileName__.actions.ts__tmpl__ b/packages/schematics/src/ngrx/files/+state/__fileName__.actions.ts__tmpl__ index 75374f97dd..c18a0c45f6 100644 --- a/packages/schematics/src/ngrx/files/+state/__fileName__.actions.ts__tmpl__ +++ b/packages/schematics/src/ngrx/files/+state/__fileName__.actions.ts__tmpl__ @@ -1,7 +1,12 @@ -export interface SomeAction { - type: 'SOME_ACTION'; +export interface LoadData { + type: 'LOAD_DATA'; payload: {}; } -export type <%= className %>Action = SomeAction; +export interface DataLoaded { + type: 'DATA_LOADED'; + payload: {}; +} + +export type <%= className %>Action = LoadData | DataLoaded; diff --git a/packages/schematics/src/ngrx/files/+state/__fileName__.effects.spec.ts__tmpl__ b/packages/schematics/src/ngrx/files/+state/__fileName__.effects.spec.ts__tmpl__ index cc0aa2faec..9ce926358b 100644 --- a/packages/schematics/src/ngrx/files/+state/__fileName__.effects.spec.ts__tmpl__ +++ b/packages/schematics/src/ngrx/files/+state/__fileName__.effects.spec.ts__tmpl__ @@ -1,16 +1,36 @@ +import {TestBed} from '@angular/core/testing'; +import {StoreModule} from '@ngrx/store'; import {Actions} from '@ngrx/effects'; +import {provideMockActions} from '@ngrx/effects/testing'; +import {DataPersistence} from '@nrwl/nx'; import {readAll, hot} from '@nrwl/nx/testing'; import {<%= className %>Effects} from './<%= fileName %>.effects'; import {of} from 'rxjs/observable/of'; describe('<%= className %>Effects', () => { + let actions; + let effects: <%= className %>Effects; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + StoreModule.forRoot({}), + ], + providers: [ + <%= className %>Effects, + DataPersistence, + provideMockActions(() => actions) + ], + }); + + effects = TestBed.get(<%= className %>Effects); + }); + describe('someEffect', () => { it('should work', async () => { - const actions = new Actions(hot('-a-|', {a: {type: 'SOME_ACTION'}})); - const effects = new <%= className %>Effects(actions); - - expect(await readAll(effects.someEffect)).toEqual([ - {type: 'OTHER_ACTION'} + actions = hot('-a-|', {a: {type: 'LOAD_DATA'}}); + expect(await readAll(effects.loadData)).toEqual([ + {type: 'DATA_LOADED', payload: {}} ]); }); }); diff --git a/packages/schematics/src/ngrx/files/+state/__fileName__.effects.ts__tmpl__ b/packages/schematics/src/ngrx/files/+state/__fileName__.effects.ts__tmpl__ index 7e2a893b81..6b2a726fb6 100644 --- a/packages/schematics/src/ngrx/files/+state/__fileName__.effects.ts__tmpl__ +++ b/packages/schematics/src/ngrx/files/+state/__fileName__.effects.ts__tmpl__ @@ -1,14 +1,25 @@ import {Injectable} from '@angular/core'; import {Effect, Actions} from '@ngrx/effects'; +import {DataPersistence} from '@nrwl/nx'; import {of} from 'rxjs/observable/of'; import 'rxjs/add/operator/switchMap'; +import {<%= className %>State} from './<%= fileName %>.interfaces'; +import {LoadData, DataLoaded} from './<%= fileName %>.actions'; @Injectable() export class <%= className %>Effects { - @Effect() someEffect = this.actions.ofType('SOME_ACTION').switchMap((a) => { - // process the action - return of({type: 'OTHER_ACTION'}); + @Effect() loadData = this.d.pessimisticUpdate('LOAD_DATA', { + run(a: LoadData, state: <%= className %>State) { + return { + type: 'DATA_LOADED', + payload: {} + }; + }, + + onError(a: LoadData, error) { + console.error('Error', error); + } }); - constructor(private actions: Actions) {} + constructor(private actions: Actions, private d: DataPersistence<<%= className %>State>) {} } diff --git a/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.spec.ts__tmpl__ b/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.spec.ts__tmpl__ index 85a66a70ff..de7aab3e7b 100644 --- a/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.spec.ts__tmpl__ +++ b/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.spec.ts__tmpl__ @@ -1,12 +1,12 @@ import { <%= propertyName %>Reducer } from './<%= fileName %>.reducer'; import { <%= propertyName %>InitialState } from './<%= fileName %>.init'; import { <%= className %> } from './<%= fileName %>.interfaces'; -import { SomeAction } from './<%= fileName %>.actions'; +import { DataLoaded } from './<%= fileName %>.actions'; describe('<%= propertyName %>Reducer', () => { it('should work', () => { const state: <%= className %> = {}; - const action: SomeAction = {type: 'SOME_ACTION', payload: {}}; + const action: DataLoaded = {type: 'DATA_LOADED', payload: {}}; const actual = <%= propertyName %>Reducer(state, action); expect(actual).toEqual({}); }); diff --git a/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.ts__tmpl__ b/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.ts__tmpl__ index c075d6b6c6..1e5643b735 100644 --- a/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.ts__tmpl__ +++ b/packages/schematics/src/ngrx/files/+state/__fileName__.reducer.ts__tmpl__ @@ -3,7 +3,7 @@ import {<%= className %>Action} from './<%= fileName %>.actions'; export function <%= propertyName %>Reducer(state: <%= className %>, action: <%= className %>Action): <%= className %> { switch (action.type) { - case 'SOME_ACTION': { + case 'DATA_LOADED': { return {...state, ...action.payload}; } default: { diff --git a/packages/schematics/src/ngrx/index.ts b/packages/schematics/src/ngrx/index.ts index af93f03262..72504a34bd 100644 --- a/packages/schematics/src/ngrx/index.ts +++ b/packages/schematics/src/ngrx/index.ts @@ -26,13 +26,14 @@ function addImportsToModule(name: string, options: Schema): Rule { const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true); if (options.onlyEmptyRoot) { - const reducer = `StoreModule.forRoot({})`; - const effects = `EffectsModule.forRoot([])`; - insert(host, modulePath, [ insertImport(source, modulePath, 'StoreModule', '@ngrx/store'), insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'), - ...addImportToModule(source, modulePath, reducer), ...addImportToModule(source, modulePath, effects) + insertImport(source, modulePath, 'StoreDevtoolsModule', '@ngrx/store-devtools'), + insertImport(source, modulePath, 'environment', '../environments/environment'), + ...addImportToModule(source, modulePath, `StoreModule.forRoot({})`), + ...addImportToModule(source, modulePath, `EffectsModule.forRoot([])`), + ...addImportToModule(source, modulePath, `!environment.production ? StoreDevtoolsModule.instrument() : []`) ]); return host; @@ -45,20 +46,34 @@ function addImportsToModule(name: string, options: Schema): Rule { const effectsName = `${toClassName(name)}Effects`; const initName = `${toPropertyName(name)}InitialState`; - const effects = - options.root ? `EffectsModule.forRoot([${effectsName}])` : `EffectsModule.forFeature([${effectsName}])`; - const reducer = options.root ? - `StoreModule.forRoot(${reducerName}, {initialState: ${initName}})` : - `StoreModule.forFeature('${toPropertyName(name)}', ${reducerName}, {initialState: ${initName}})`; - - insert(host, modulePath, [ + const common = [ insertImport(source, modulePath, 'StoreModule', '@ngrx/store'), insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'), insertImport(source, modulePath, reducerName, reducerPath), insertImport(source, modulePath, initName, initPath), - insertImport(source, modulePath, effectsName, effectsPath), ...addImportToModule(source, modulePath, reducer), - ...addImportToModule(source, modulePath, effects), ...addProviderToModule(source, modulePath, effectsName) - ]); + insertImport(source, modulePath, effectsName, effectsPath), + ...addProviderToModule(source, modulePath, effectsName) + ]; + + if (options.root) { + insert(host, modulePath, [ + ...common, + insertImport(source, modulePath, 'StoreDevtoolsModule', '@ngrx/store-devtools'), + insertImport(source, modulePath, 'environment', '../environments/environment'), + ...addImportToModule(source, modulePath, `StoreModule.forRoot(${reducerName}, {initialState: ${initName}})`), + ...addImportToModule(source, modulePath, `EffectsModule.forRoot([${effectsName}])`), + ...addImportToModule(source, modulePath, `!environment.production ? StoreDevtoolsModule.instrument() : []`), + ]); + } else { + insert(host, modulePath, [ + ...common, + ...addImportToModule( + source, modulePath, + `StoreModule.forFeature('${toPropertyName(name)}', ${reducerName}, {initialState: ${initName}})`), + ...addImportToModule(source, modulePath, `EffectsModule.forFeature([${effectsName}])`) + ]); + } + return host; } }; @@ -83,6 +98,9 @@ function addNgRxToPackageJson() { if (!json['dependencies']['@ngrx/effects']) { json['dependencies']['@ngrx/effects'] = ngrxVersion; } + if (!json['dependencies']['@ngrx/store-devtools']) { + json['dependencies']['@ngrx/store-devtools'] = ngrxVersion; + } host.overwrite('package.json', JSON.stringify(json, null, 2)); return host; }; diff --git a/packages/schematics/src/utility/lib-versions.ts b/packages/schematics/src/utility/lib-versions.ts index 27b9c1a6d4..0976593738 100644 --- a/packages/schematics/src/utility/lib-versions.ts +++ b/packages/schematics/src/utility/lib-versions.ts @@ -1,4 +1,4 @@ export const angularJsVersion = '1.6.6'; -export const ngrxVersion = '4.0.3'; +export const ngrxVersion = '^4.0.0'; export const nxVersion = 'nrwl/nx-build'; export const schematicsVersion = 'nrwl/schematics-build'; diff --git a/yarn.lock b/yarn.lock index 9c79721f70..a495b1b6c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -135,6 +135,10 @@ version "4.0.3" resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-4.0.3.tgz#5f924914a8dda136b049fc6c7ce9fe177f44be97" +"@ngrx/store-devtools@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-4.0.0.tgz#b79c24773217df7fd9735ad21f9cbf2533c96e04" + "@ngrx/store@4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9"