Skip to content

Commit

Permalink
feat(schematics): add support for reducer creators
Browse files Browse the repository at this point in the history
Closes #1764, 1766
  • Loading branch information
brandonroberts committed Apr 23, 2019
1 parent be106c9 commit 42097f0
Show file tree
Hide file tree
Showing 29 changed files with 242 additions and 164 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import { createAction, union } from '@ngrx/store';
import { createAction } from '@ngrx/store';

export const load<%= classify(name) %>s = createAction('[<%= classify(name) %>] Load <%= classify(name) %>s');
<% if (api) { %>export const load<%= classify(name) %>sSuccess = createAction('[<%= classify(name) %>] Load <%= classify(name) %>s Success');<% } %>
<% if (api) { %>export const load<%= classify(name) %>sFailure = createAction('[<%= classify(name) %>] Load <%= classify(name) %>s Failure');<% } %>

const all = union({
load<%= classify(name) %>s,
<% if (api) { %>
load<%= classify(name) %>sSuccess,
load<%= classify(name) %>sFailure
<% } %>
});
export Union = typeof all;
2 changes: 1 addition & 1 deletion modules/schematics/src/action/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ describe('Action Schematic', () => {
});

describe('action creators', () => {
const creatorOptions = { ...defaultOptions, actionCreators: true };
const creatorOptions = { ...defaultOptions, creators: true };

it('should create a const for the action creator', () => {
const tree = schematicRunner.runSchematic(
Expand Down
2 changes: 1 addition & 1 deletion modules/schematics/src/action/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function(options: ActionOptions): Rule {
options.path = parsedPath.path;

const templateSource = apply(
url(options.actionCreators ? './creator-files' : './files'),
url(options.creators ? './creator-files' : './files'),
[
options.spec
? noop()
Expand Down
6 changes: 3 additions & 3 deletions modules/schematics/src/action/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
"Specifies if api success and failure actions should be generated.",
"aliases": ["a"]
},
"actionCreators": {
"creators": {
"type": "boolean",
"default": false,
"description":
"Specifies whether to generate action creators instead of action classes.",
"aliases": ["ac"]
"Specifies whether to use creator functions for handling actions and reducers.",
"aliases": ["c"]
}
},
"required": []
Expand Down
6 changes: 3 additions & 3 deletions modules/schematics/src/action/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export interface Schema {
api?: boolean;

/**
* Specifies whether to generate action creators
* instead of action classes.
* Specifies whether to use creator functions for
* handling actions and reducers.
*/
actionCreators?: boolean;
creators?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { Injectable } from '@angular/core';
import { Actions, <%= effectMethod %><% if (feature) { %>, ofType<% } %> } from '@ngrx/effects';
<% if (feature && api) { %>import { catchError, map, concatMap } from 'rxjs/operators';
import { EMPTY, of } from 'rxjs';
<% if (!effectCreators) {%>import { Load<%= classify(name) %>sFailure, Load<%= classify(name) %>sSuccess, <%= classify(name) %>ActionTypes, <%= classify(name) %>Actions } from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (effectCreators) {%>import * as <%= classify(name) %>Actions from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (!creators) {%>import { Load<%= classify(name) %>sFailure, Load<%= classify(name) %>sSuccess, <%= classify(name) %>ActionTypes, <%= classify(name) %>Actions } from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (creators) {%>import * as <%= classify(name) %>Actions from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% } %>
<% if (feature && !api) { %>import { concatMap } from 'rxjs/operators';
import { EMPTY } from 'rxjs';
<% if (!effectCreators) {%>import { <%= classify(name) %>ActionTypes, <%= classify(name) %>Actions } from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (effectCreators) {%>import * as <%= classify(name) %>Actions from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (!creators) {%>import { <%= classify(name) %>ActionTypes, <%= classify(name) %>Actions } from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% if (creators) {%>import * as <%= classify(name) %>Actions from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';<% } %>
<% } %>

@Injectable()
export class <%= classify(name) %>Effects {
<% if (feature && api && !effectCreators) { %>
<% if (feature && api && !creators) { %>
<%= effectStart %>
ofType(<%= classify(name) %>ActionTypes.Load<%= classify(name) %>s),
concatMap(() =>
Expand All @@ -23,7 +23,7 @@ export class <%= classify(name) %>Effects {
catchError(error => of(new Load<%= classify(name) %>sFailure({ error }))))
)
<%= effectEnd %>
<% } else if (feature && api && effectCreators) { %>
<% } else if (feature && api && creators) { %>
<%= effectStart %>
ofType(<%= classify(name) %>Actions.load<%= classify(name) %>s),
concatMap(() =>
Expand All @@ -34,22 +34,22 @@ export class <%= classify(name) %>Effects {
)
<%= effectEnd %>
<% } %>
<% if (feature && !api && !effectCreators) { %>
<% if (feature && !api && !creators) { %>
<%= effectStart %>
ofType(<%= classify(name) %>ActionTypes.Load<%= classify(name) %>s),
/** An EMPTY observable only emits completion. Replace with your own observable API request */
concatMap(() => EMPTY)
<%= effectEnd %>
<% } else if (feature && !api && effectCreators) { %>
<% } else if (feature && !api && creators) { %>
<%= effectStart %>
ofType(<%= classify(name) %>Actions.load<%= classify(name) %>s),
/** An EMPTY observable only emits completion. Replace with your own observable API request */
concatMap(() => EMPTY)
<%= effectEnd %>
<% } %>
<% if (feature && !effectCreators) { %>
<% if (feature && !creators) { %>
constructor(private actions$: Actions<<%= classify(name) %>Actions>) {}
<% } else if (feature && effectCreators) { %>
<% } else if (feature && creators) { %>
constructor(private actions$: Actions) {}
<% } else { %>
constructor(private actions$: Actions) {}
Expand Down
10 changes: 5 additions & 5 deletions modules/schematics/src/effect/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('Effect Schematic', () => {
feature: false,
root: false,
group: false,
effectCreators: false,
creators: false,
};

const projectPath = getTestProjectPath();
Expand Down Expand Up @@ -319,7 +319,7 @@ describe('Effect Schematic', () => {
});

it('should create an effect using creator function', () => {
const options = { ...defaultOptions, effectCreators: true, feature: true };
const options = { ...defaultOptions, creators: true, feature: true };

const tree = schematicRunner.runSchematic('effect', options, appTree);
const content = tree.readContent(
Expand All @@ -334,8 +334,8 @@ describe('Effect Schematic', () => {
);
});

it('should use action creators when effectCreators is enabled in a feature', () => {
const options = { ...defaultOptions, effectCreators: true, feature: true };
it('should use action creators when creators is enabled in a feature', () => {
const options = { ...defaultOptions, creators: true, feature: true };

const tree = schematicRunner.runSchematic('effect', options, appTree);
const content = tree.readContent(
Expand All @@ -352,7 +352,7 @@ describe('Effect Schematic', () => {
it('should create an api effect using creator function', () => {
const options = {
...defaultOptions,
effectCreators: true,
creators: true,
api: true,
feature: true,
};
Expand Down
18 changes: 9 additions & 9 deletions modules/schematics/src/effect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,19 @@ function addImportToNgModule(options: EffectOptions): Rule {
};
}

function getEffectMethod(effectCreators?: boolean) {
return effectCreators ? 'createEffect' : 'Effect';
function getEffectMethod(creators?: boolean) {
return creators ? 'createEffect' : 'Effect';
}

function getEffectStart(name: string, effectCreators?: boolean): string {
function getEffectStart(name: string, creators?: boolean): string {
const effectName = stringUtils.classify(name);
return effectCreators
return creators
? `load${effectName}s$ = createEffect(() => this.actions$.pipe(`
: '@Effect()\n' + ` load${effectName}s$ = this.actions$.pipe(`;
}

function getEffectEnd(effectCreators?: boolean) {
return effectCreators ? '));' : ');';
function getEffectEnd(creators?: boolean) {
return creators ? '));' : ');';
}

export default function(options: EffectOptions): Rule {
Expand All @@ -131,9 +131,9 @@ export default function(options: EffectOptions): Rule {
options.flat ? '' : s,
options.group ? 'effects' : ''
),
effectMethod: getEffectMethod(options.effectCreators),
effectStart: getEffectStart(options.name, options.effectCreators),
effectEnd: getEffectEnd(options.effectCreators),
effectMethod: getEffectMethod(options.creators),
effectStart: getEffectStart(options.name, options.creators),
effectEnd: getEffectEnd(options.creators),
...(options as object),
} as any),
move(parsedPath.path),
Expand Down
7 changes: 4 additions & 3 deletions modules/schematics/src/effect/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@
"Specifies if effect has api success and failure actions wired up",
"aliases": ["a"]
},
"effectCreators": {
"creators": {
"type": "boolean",
"default": false,
"description": "Specifies whether to use the effect creators function",
"aliases": ["ec"]
"description":
"Specifies whether to use creator functions for handling actions and reducers.",
"aliases": ["c"]
}
},
"required": []
Expand Down
5 changes: 3 additions & 2 deletions modules/schematics/src/effect/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export interface Schema {
api?: boolean;

/**
* Specifies if the effect creation uses 'createEffect'
* Specifies whether to use creator functions for
* handling actions, reducers, and effects.
*/
effectCreators?: boolean;
creators?: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,53 @@
import { createAction, props, union } from '@ngrx/store';
import { createAction, props } from '@ngrx/store';
import { Update } from '@ngrx/entity';

import { <%= classify(name) %> } from '<%= featurePath(group, flat, "models", dasherize(name)) %><%= dasherize(name) %>.model';

export const load<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Load <%= classify(name) %>s', props<{ <%= camelize(name) %>s: <%= classify(name) %>[] }>());
export const add<%= classify(name) %> = createAction('[<%= classify(name) %>/API] Add <%= classify(name) %>', props<{ <%= camelize(name) %>: <%= classify(name) %> }>());
export const upsert<%= classify(name) %> = createAction('[<%= classify(name) %>/API] Upsert <%= classify(name) %>', props<{ <%= camelize(name) %>: <%= classify(name) %> }>());
export const add<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Add <%= classify(name) %>s', props<{ <%= camelize(name) %>: <%= classify(name) %> }>());
export const upsert<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Upsert <%= classify(name) %>s', props<{ <%= camelize(name) %>s: <%= classify(name) %>[] }>());
export const update<%= classify(name) %> = createAction('[<%= classify(name) %>/API] Update <%= classify(name) %>', props<{ <%= camelize(name) %>: Update<<%= classify(name) %>> }>());
export const update<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Update <%= classify(name) %>s', props<{ <%= camelize(name) %>s: Update<<%= classify(name) %>>[] }>());
export const delete<%= classify(name) %> = createAction('[<%= classify(name) %>/API] Delete <%= classify(name) %>', props<{ id: string }>());
export const delete<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Delete <%= classify(name) %>s', props<{ id: string[] }>());
export const clear<%= classify(name) %>s = createAction('[<%= classify(name) %>/API] Clear <%= classify(name) %>s');

const all = union({
load<%= classify(name) %>s,
add<%= classify(name) %>,
upsert<%= classify(name) %>,
add<%= classify(name) %>s,
upsert<%= classify(name) %>s,
update<%= classify(name) %>,
update<%= classify(name) %>s,
delete<%= classify(name) %>,
delete<%= classify(name) %>s,
clear<%= classify(name) %>s
});
export type Union = typeof all;
export const load<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Load <%= classify(name) %>s',
props<{ <%= camelize(name) %>s: <%= classify(name) %>[] }>()
);

export const add<%= classify(name) %> = createAction(
'[<%= classify(name) %>/API] Add <%= classify(name) %>',
props<{ <%= camelize(name) %>: <%= classify(name) %> }>()
);

export const upsert<%= classify(name) %> = createAction(
'[<%= classify(name) %>/API] Upsert <%= classify(name) %>',
props<{ <%= camelize(name) %>: <%= classify(name) %> }>()
);

export const add<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Add <%= classify(name) %>s',
props<{ <%= camelize(name) %>: <%= classify(name) %> }>()
);

export const upsert<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Upsert <%= classify(name) %>s',
props<{ <%= camelize(name) %>s: <%= classify(name) %>[] }>()
);

export const update<%= classify(name) %> = createAction(
'[<%= classify(name) %>/API] Update <%= classify(name) %>',
props<{ <%= camelize(name) %>: Update<<%= classify(name) %>> }>()
);

export const update<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Update <%= classify(name) %>s',
props<{ <%= camelize(name) %>s: Update<<%= classify(name) %>>[] }>()
);

export const delete<%= classify(name) %> = createAction(
'[<%= classify(name) %>/API] Delete <%= classify(name) %>',
props<{ id: string }>()
);

export const delete<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Delete <%= classify(name) %>s',
props<{ id: string[] }>()
);

export const clear<%= classify(name) %>s = createAction(
'[<%= classify(name) %>/API] Clear <%= classify(name) %>s'
);
Loading

0 comments on commit 42097f0

Please sign in to comment.