feat(schematics): improve ngrx code generation
This commit is contained in:
parent
a0440688c3
commit
c603a834a7
@ -32,6 +32,7 @@
|
|||||||
"@ngrx/store": "4.0.3",
|
"@ngrx/store": "4.0.3",
|
||||||
"@ngrx/router-store": "4.0.3",
|
"@ngrx/router-store": "4.0.3",
|
||||||
"@ngrx/effects": "4.0.3",
|
"@ngrx/effects": "4.0.3",
|
||||||
|
"@ngrx/store-devtools": "^4.0.0",
|
||||||
"typescript": "2.4.2",
|
"typescript": "2.4.2",
|
||||||
"@types/node": "8.0.7",
|
"@types/node": "8.0.7",
|
||||||
"@types/jasmine": "2.5.53",
|
"@types/jasmine": "2.5.53",
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
export interface SomeAction {
|
export interface LoadData {
|
||||||
type: 'SOME_ACTION';
|
type: 'LOAD_DATA';
|
||||||
payload: {};
|
payload: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type <%= className %>Action = SomeAction;
|
export interface DataLoaded {
|
||||||
|
type: 'DATA_LOADED';
|
||||||
|
payload: {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type <%= className %>Action = LoadData | DataLoaded;
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,36 @@
|
|||||||
|
import {TestBed} from '@angular/core/testing';
|
||||||
|
import {StoreModule} from '@ngrx/store';
|
||||||
import {Actions} from '@ngrx/effects';
|
import {Actions} from '@ngrx/effects';
|
||||||
|
import {provideMockActions} from '@ngrx/effects/testing';
|
||||||
|
import {DataPersistence} from '@nrwl/nx';
|
||||||
import {readAll, hot} from '@nrwl/nx/testing';
|
import {readAll, hot} from '@nrwl/nx/testing';
|
||||||
import {<%= className %>Effects} from './<%= fileName %>.effects';
|
import {<%= className %>Effects} from './<%= fileName %>.effects';
|
||||||
import {of} from 'rxjs/observable/of';
|
import {of} from 'rxjs/observable/of';
|
||||||
|
|
||||||
describe('<%= className %>Effects', () => {
|
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', () => {
|
describe('someEffect', () => {
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
const actions = new Actions(hot('-a-|', {a: {type: 'SOME_ACTION'}}));
|
actions = hot('-a-|', {a: {type: 'LOAD_DATA'}});
|
||||||
const effects = new <%= className %>Effects(actions);
|
expect(await readAll(effects.loadData)).toEqual([
|
||||||
|
{type: 'DATA_LOADED', payload: {}}
|
||||||
expect(await readAll(effects.someEffect)).toEqual([
|
|
||||||
{type: 'OTHER_ACTION'}
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,14 +1,25 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {Effect, Actions} from '@ngrx/effects';
|
import {Effect, Actions} from '@ngrx/effects';
|
||||||
|
import {DataPersistence} from '@nrwl/nx';
|
||||||
import {of} from 'rxjs/observable/of';
|
import {of} from 'rxjs/observable/of';
|
||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
|
import {<%= className %>State} from './<%= fileName %>.interfaces';
|
||||||
|
import {LoadData, DataLoaded} from './<%= fileName %>.actions';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class <%= className %>Effects {
|
export class <%= className %>Effects {
|
||||||
@Effect() someEffect = this.actions.ofType('SOME_ACTION').switchMap((a) => {
|
@Effect() loadData = this.d.pessimisticUpdate('LOAD_DATA', {
|
||||||
// process the action
|
run(a: LoadData, state: <%= className %>State) {
|
||||||
return of({type: 'OTHER_ACTION'});
|
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>) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { <%= propertyName %>Reducer } from './<%= fileName %>.reducer';
|
import { <%= propertyName %>Reducer } from './<%= fileName %>.reducer';
|
||||||
import { <%= propertyName %>InitialState } from './<%= fileName %>.init';
|
import { <%= propertyName %>InitialState } from './<%= fileName %>.init';
|
||||||
import { <%= className %> } from './<%= fileName %>.interfaces';
|
import { <%= className %> } from './<%= fileName %>.interfaces';
|
||||||
import { SomeAction } from './<%= fileName %>.actions';
|
import { DataLoaded } from './<%= fileName %>.actions';
|
||||||
|
|
||||||
describe('<%= propertyName %>Reducer', () => {
|
describe('<%= propertyName %>Reducer', () => {
|
||||||
it('should work', () => {
|
it('should work', () => {
|
||||||
const state: <%= className %> = {};
|
const state: <%= className %> = {};
|
||||||
const action: SomeAction = {type: 'SOME_ACTION', payload: {}};
|
const action: DataLoaded = {type: 'DATA_LOADED', payload: {}};
|
||||||
const actual = <%= propertyName %>Reducer(state, action);
|
const actual = <%= propertyName %>Reducer(state, action);
|
||||||
expect(actual).toEqual({});
|
expect(actual).toEqual({});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import {<%= className %>Action} from './<%= fileName %>.actions';
|
|||||||
|
|
||||||
export function <%= propertyName %>Reducer(state: <%= className %>, action: <%= className %>Action): <%= className %> {
|
export function <%= propertyName %>Reducer(state: <%= className %>, action: <%= className %>Action): <%= className %> {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SOME_ACTION': {
|
case 'DATA_LOADED': {
|
||||||
return {...state, ...action.payload};
|
return {...state, ...action.payload};
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
@ -26,13 +26,14 @@ function addImportsToModule(name: string, options: Schema): Rule {
|
|||||||
const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);
|
const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);
|
||||||
|
|
||||||
if (options.onlyEmptyRoot) {
|
if (options.onlyEmptyRoot) {
|
||||||
const reducer = `StoreModule.forRoot({})`;
|
|
||||||
const effects = `EffectsModule.forRoot([])`;
|
|
||||||
|
|
||||||
insert(host, modulePath, [
|
insert(host, modulePath, [
|
||||||
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
||||||
insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'),
|
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;
|
return host;
|
||||||
|
|
||||||
@ -45,20 +46,34 @@ function addImportsToModule(name: string, options: Schema): Rule {
|
|||||||
const effectsName = `${toClassName(name)}Effects`;
|
const effectsName = `${toClassName(name)}Effects`;
|
||||||
const initName = `${toPropertyName(name)}InitialState`;
|
const initName = `${toPropertyName(name)}InitialState`;
|
||||||
|
|
||||||
const effects =
|
const common = [
|
||||||
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, [
|
|
||||||
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
insertImport(source, modulePath, 'StoreModule', '@ngrx/store'),
|
||||||
insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'),
|
insertImport(source, modulePath, 'EffectsModule', '@ngrx/effects'),
|
||||||
insertImport(source, modulePath, reducerName, reducerPath),
|
insertImport(source, modulePath, reducerName, reducerPath),
|
||||||
insertImport(source, modulePath, initName, initPath),
|
insertImport(source, modulePath, initName, initPath),
|
||||||
insertImport(source, modulePath, effectsName, effectsPath), ...addImportToModule(source, modulePath, reducer),
|
insertImport(source, modulePath, effectsName, effectsPath),
|
||||||
...addImportToModule(source, modulePath, effects), ...addProviderToModule(source, modulePath, effectsName)
|
...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;
|
return host;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -83,6 +98,9 @@ function addNgRxToPackageJson() {
|
|||||||
if (!json['dependencies']['@ngrx/effects']) {
|
if (!json['dependencies']['@ngrx/effects']) {
|
||||||
json['dependencies']['@ngrx/effects'] = ngrxVersion;
|
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));
|
host.overwrite('package.json', JSON.stringify(json, null, 2));
|
||||||
return host;
|
return host;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export const angularJsVersion = '1.6.6';
|
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 nxVersion = 'nrwl/nx-build';
|
||||||
export const schematicsVersion = 'nrwl/schematics-build';
|
export const schematicsVersion = 'nrwl/schematics-build';
|
||||||
|
|||||||
@ -135,6 +135,10 @@
|
|||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-4.0.3.tgz#5f924914a8dda136b049fc6c7ce9fe177f44be97"
|
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":
|
"@ngrx/store@4.0.3":
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9"
|
resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-4.0.3.tgz#36abacdfa19bfb8506e40de80bae06050a1e15e9"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user