Skip to content

Commit

Permalink
feat(nx): update to NgRx 8 and add schematics support for creators an…
Browse files Browse the repository at this point in the history
…d entities

Move addUpdateTask util function to @nrwl/workspace to run updates from @nrwl/angular migrations
Run update migration to latest version for NgRx if installed
  • Loading branch information
brandonroberts authored and vsavkin committed Jul 17, 2019
1 parent 93aac33 commit 6516176
Show file tree
Hide file tree
Showing 41 changed files with 973 additions and 587 deletions.
507 changes: 71 additions & 436 deletions docs/angular/guides/misc-ngrx.md

Large diffs are not rendered by default.

42 changes: 33 additions & 9 deletions docs/api-angular/schematics/ngrx.md
Expand Up @@ -17,64 +17,88 @@ Default: `+state`

Type: `string`

Override the name of the folder used to contain/group the NgRx files: contains actions, effects, reducers. selectors. (e.g., +state)
The name of the folder used to contain/group the generated NgRx files.

### facade

Default: `false`

Type: `boolean`

Create a Facade class for the the Feature (e.g., --facade).
Create a Facade class for the the Feature.

### minimal

Default: `false`

Type: `boolean`

Only register the root state management setup or feature state.

### module

Type: `string`

Path to ngModule; host directory will contain the new '+state' directory (e.g., libs/comments/src/lib/comments-state.module.ts).
The path to NgModule where the feature state will be registered. The host directory will create/use the new state directory.

### name

Type: `string`

Name of the NgRx feature (e.g., Products, Users, etc.). Recommended to use plural form for name.
Name of the NgRx feature state, such as "products" or "users"). Recommended to use the plural form of the name.

### onlyAddFiles

Default: `false`

Type: `boolean`

Only add new NgRx files, without changing the module file (e.g., --onlyAddFiles).
**Deprecated**, use `skipImport`. Only add new NgRx files, without changing the module file (e.g., --onlyAddFiles).

### onlyEmptyRoot

Default: `false`

Type: `boolean`

Do not generate any files. Only generate StoreModule.forRoot and EffectsModule.forRoot (e.g., --onlyEmptyRoot).
**Deprecated**, use `minimal`. Do not generate any files. Only generate StoreModule.forRoot and EffectsModule.forRoot (e.g., --onlyEmptyRoot).

### root

Default: `false`

Type: `boolean`

Add StoreModule.forRoot and EffectsModule.forRoot() instead of forFeature (e.g., --root).
Setup root or feature state management with NgRx.

### skipFormat

Default: `false`

Type: `boolean`

Skip formatting files
Skip formatting of generated files.

### skipImport

Default: `false`

Type: `boolean`

Generate NgRx feature files without registering the feature in the NgModule.

### skipPackageJson

Default: `false`

Type: `boolean`

Do not add NgRx dependencies to package.json (e.g., --skipPackageJson)
Do not update the package.json with NgRx dependencies.

### syntax

Default: `classes`

Type: `string`

Specifies whether to use class-based or creator functions for actions, reducers, and effects.
2 changes: 1 addition & 1 deletion docs/map.json
Expand Up @@ -137,7 +137,7 @@
"id": "react-and-angular"
},
{
"name": "Setting Up NgRx",
"name": "Using NgRx",
"id": "misc-ngrx"
},
{
Expand Down
31 changes: 31 additions & 0 deletions e2e/ngrx.test.ts
Expand Up @@ -36,4 +36,35 @@ describe('ngrx', () => {
expectTestsPass(await runCLIAsync(`test ${myapp} --no-watch`));
expectTestsPass(await runCLIAsync(`test ${mylib} --no-watch`));
}, 1000000);

it('should work with creators', async () => {
ensureProject();

const myapp = uniq('myapp');
runCLI(`generate @nrwl/angular:app ${myapp} --routing --no-interactive`);

// Generate root ngrx state management
runCLI(
`generate @nrwl/angular:ngrx users --module=apps/${myapp}/src/app/app.module.ts --root --minimal --syntax=creators`
);
const packageJson = readJson('package.json');
expect(packageJson.dependencies['@ngrx/entity']).toBeDefined();
expect(packageJson.dependencies['@ngrx/store']).toBeDefined();
expect(packageJson.dependencies['@ngrx/effects']).toBeDefined();
expect(packageJson.dependencies['@ngrx/router-store']).toBeDefined();
expect(packageJson.devDependencies['@ngrx/schematics']).toBeDefined();
expect(packageJson.devDependencies['@ngrx/store-devtools']).toBeDefined();

const mylib = uniq('mylib');
// Generate feature library and ngrx state within that library
runCLI(`g @nrwl/angular:lib ${mylib} --prefix=fl`);
runCLI(
`generate @nrwl/angular:ngrx flights --module=libs/${mylib}/src/lib/${mylib}.module.ts --facade --syntax=creators`
);

expect(runCLI(`build ${myapp}`)).toContain('chunk {main} main-es2015.js,');
expect(runCLI(`build ${myapp}`)).toContain('chunk {main} main-es5.js,');
expectTestsPass(await runCLIAsync(`test ${myapp} --no-watch`));
expectTestsPass(await runCLIAsync(`test ${mylib} --no-watch`));
}, 1000000);
});
13 changes: 7 additions & 6 deletions package.json
Expand Up @@ -43,11 +43,12 @@
"@nestjs/platform-express": "^6.2.4",
"@nestjs/schematics": "^6.3.0",
"@nestjs/testing": "^6.2.4",
"@ngrx/effects": "7.1.0",
"@ngrx/router-store": "7.1.0",
"@ngrx/schematics": "7.1.0",
"@ngrx/store": "7.1.0",
"@ngrx/store-devtools": "7.1.0",
"@ngrx/effects": "8.1.0",
"@ngrx/entity": "8.1.0",
"@ngrx/router-store": "8.1.0",
"@ngrx/schematics": "8.1.0",
"@ngrx/store": "8.1.0",
"@ngrx/store-devtools": "8.1.0",
"@schematics/angular": "8.0.0",
"@types/express": "4.16.0",
"@types/jasmine": "~2.8.6",
Expand Down Expand Up @@ -80,7 +81,7 @@
"identity-obj-proxy": "3.0.0",
"ignore": "^5.0.4",
"jasmine-core": "~2.99.1",
"jasmine-marbles": "~0.5.0",
"jasmine-marbles": "~0.6.0",
"jasmine-spec-reporter": "~4.2.1",
"jest": "^24.1.0",
"jest-jasmine2": "^24.1.0",
Expand Down
8 changes: 7 additions & 1 deletion packages/angular/migrations.json
@@ -1,3 +1,9 @@
{
"schematics": {}
"schematics": {
"upgrade-ngrx-8-0": {
"version": "8.3.0-beta.1",
"description": "Upgrades NgRx dependencies to version 8, and runs migrations for breaking changes",
"factory": "./src/migrations/update-8-3-0/upgrade-ngrx-8-0"
}
}
}
1 change: 1 addition & 0 deletions packages/angular/ng-package.json
Expand Up @@ -4,6 +4,7 @@
"entryFile": "index.ts",
"umdModuleIds": {
"@ngrx/effects": "ngrx.effects",
"@ngrx/entity": "ngrx.entity",
"@ngrx/router-store": "ngrx.routerStore",
"@ngrx/store": "ngrx.store",
"jasmine-marbles": "jasmine-marbles"
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/package.json
Expand Up @@ -36,6 +36,6 @@
"@nrwl/jest": "*",
"@angular-devkit/schematics": "8.0.1",
"@schematics/angular": "8.0.1",
"jasmine-marbles": "~0.5.0"
"jasmine-marbles": "~0.6.0"
}
}
84 changes: 76 additions & 8 deletions packages/angular/spec/data-persistence.spec.ts
Expand Up @@ -80,8 +80,16 @@ describe('DataPersistence', () => {
TestBed.configureTestingModule({
declarations: [RootCmp, TodoComponent],
imports: [
StoreModule.forRoot({ todos: todosReducer, user: userReducer }),
StoreRouterConnectingModule,
StoreModule.forRoot(
{ todos: todosReducer, user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
),
StoreRouterConnectingModule.forRoot(),
RouterTestingModule.withRoutes([
{ path: 'todo/:id', component: TodoComponent }
]),
Expand Down Expand Up @@ -278,7 +286,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down Expand Up @@ -341,7 +359,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down Expand Up @@ -405,7 +433,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down Expand Up @@ -472,7 +510,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down Expand Up @@ -519,7 +567,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down Expand Up @@ -588,7 +646,17 @@ describe('DataPersistence', () => {
actions = new Subject<any>();
TestBed.configureTestingModule({
providers: [TodoEffects, provideMockActions(() => actions)],
imports: [StoreModule.forRoot({ user: userReducer })]
imports: [
StoreModule.forRoot(
{ user: userReducer },
{
runtimeChecks: {
strictStateImmutability: false,
strictStateSerializability: false
}
}
)
]
});
});

Expand Down
18 changes: 18 additions & 0 deletions packages/angular/src/migrations/update-8-3-0/upgrade-ngrx-8-0.ts
@@ -0,0 +1,18 @@
import { chain, Tree, noop } from '@angular-devkit/schematics';
import { addUpdateTask, readJsonInTree, formatFiles } from '@nrwl/workspace';

const runNgrxUpdate = addUpdateTask('@ngrx/store', '8.1.0');

const updateNgrx = (host: Tree) => {
const { dependencies } = readJsonInTree(host, 'package.json');

if (dependencies && dependencies['@ngrx/store']) {
return chain([runNgrxUpdate, formatFiles()]);
}

return noop();
};

export default function() {
return chain([updateNgrx]);
}
8 changes: 4 additions & 4 deletions packages/angular/src/runtime/nx/data-persistence.ts
Expand Up @@ -2,7 +2,7 @@ import { Injectable, Type } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Actions, ofType } from '@ngrx/effects';
import { ROUTER_NAVIGATION, RouterNavigationAction } from '@ngrx/router-store';
import { Action, Store } from '@ngrx/store';
import { Action, Store, ActionCreator } from '@ngrx/store';
import { Observable, of } from 'rxjs';
import {
catchError,
Expand Down Expand Up @@ -230,7 +230,7 @@ export class DataPersistence<T> {
* ```
*/
pessimisticUpdate<A extends Action = Action>(
actionType: string,
actionType: string | ActionCreator,
opts: PessimisticUpdateOpts<T, A>
): Observable<any> {
return this.actions.pipe(
Expand Down Expand Up @@ -287,7 +287,7 @@ export class DataPersistence<T> {
* ```
*/
optimisticUpdate<A extends Action = Action>(
actionType: string,
actionType: string | ActionCreator,
opts: OptimisticUpdateOpts<T, A>
): Observable<any> {
return this.actions.pipe(
Expand Down Expand Up @@ -365,7 +365,7 @@ export class DataPersistence<T> {
* it will only run the last one.
*/
fetch<A extends Action = Action>(
actionType: string,
actionType: string | ActionCreator,
opts: FetchOpts<T, A>
): Observable<any> {
return this.actions.pipe(
Expand Down

0 comments on commit 6516176

Please sign in to comment.