Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(schematics): add support for create effect to schematics #1725

Merged

Conversation

itayod
Copy link
Contributor

@itayod itayod commented Apr 10, 2019

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

[ ] Bugfix
[ ] Feature
[ ] Code style update (formatting, local variables)
[ ] Refactoring (no functional changes, no api changes)
[ ] Build related changes
[ ] CI related changes
[ ] Documentation content changes
[ ] Other... Please describe:

Closes #1682

What is the new behavior?

add support for createEffect function in effect schematics

Does this PR introduce a breaking change?

[ ] Yes
[ ] No

@@ -35,4 +35,22 @@ export class <%= classify(name) %>Effects {
<% } else { %>
constructor(private actions$: Actions) {}
<% } %>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there was an option to extend a template that could be a nice solution here @brandonroberts @timdeschryver do you know if it's possible?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not currently

@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 10, 2019

Preview docs changes for 69b6251 at https://previews.ngrx.io/pr1725-69b6251/

@brandonroberts
Copy link
Member

We'll also need to account for using action creators with the new effect creators. Instead of using *ActionTypes, the action creator is used, and it calls the action creator instead of creating an instance of an action class.

@itayod
Copy link
Contributor Author

itayod commented Apr 10, 2019

We'll also need to account for using action creators with the new effect creators. Instead of using *ActionTypes, the action creator is used, and it calls the action creator instead of creating an instance of an action class.

Hmm I see, I will try to find a proper solution that will consider the action creator option possibility,
I wounder if there is some way of splicing the template... 🤔

@itayod itayod force-pushed the feature/effect-creator-schematics branch from 69b6251 to ac45157 Compare April 10, 2019 18:19
@itayod
Copy link
Contributor Author

itayod commented Apr 10, 2019

@brandonroberts I have updated the solution what do you think?

@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 10, 2019

Preview docs changes for ac45157 at https://previews.ngrx.io/pr1725-ac45157/

Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI build seems to be failing (as an fyi in case you missed it)

modules/schematics/src/effect/index.spec.ts Outdated Show resolved Hide resolved
modules/schematics/src/effect/index.ts Outdated Show resolved Hide resolved
modules/schematics/src/effect/index.ts Outdated Show resolved Hide resolved
modules/schematics/src/effect/schema.json Show resolved Hide resolved
modules/schematics/src/feature/schema.json Outdated Show resolved Hide resolved
@brandonroberts
Copy link
Member

@itayod it would be easier to generate parts of the template in the factory code and pass a variable to the template for output. That's probably as close as we'll get to partial templates.

@itayod itayod force-pushed the feature/effect-creator-schematics branch from ac45157 to 079517c Compare April 10, 2019 19:12
@itayod
Copy link
Contributor Author

itayod commented Apr 10, 2019

@itayod it would be easier to generate parts of the template in the factory code and pass a variable to the template for output. That's probably as close as we'll get to partial templates.

I agree that's what I just did 😄

@itayod itayod force-pushed the feature/effect-creator-schematics branch 2 times, most recently from b1cecf6 to 80ece49 Compare April 10, 2019 19:17
@brandonroberts
Copy link
Member

We can save some line breaks in the template by moving the if cases up. It was too much to type separately.

import { Injectable } from '@angular/core';
import { Actions, <% if (effectCreator) { %>createEffect<% } else { %>Effect<% } %><% if (feature) { %>, ofType<% } %> } from '@ngrx/effects';
<% if (feature && api) { %>import { catchError, map, concatMap } from 'rxjs/operators';
import { EMPTY, of } from 'rxjs';
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 (feature && !api) { %>import { concatMap } from 'rxjs/operators';
import { EMPTY } from 'rxjs';
import { <%= classify(name) %>ActionTypes, <%= classify(name) %>Actions } from '<%= featurePath(group, flat, "actions", dasherize(name)) %><%= dasherize(name) %>.actions';
<% } %>

@Injectable()
export class <%= classify(name) %>Effects {<% if (feature && api) { %>
<% if (!effectCreator) { %>@Effect()<% }%>
  <%= effectMethod %>
    ofType(<%= classify(name) %>ActionTypes.Load<%= classify(name) %>s),
    concatMap(() =>
      /** An EMPTY observable only emits completion. Replace with your own observable API request */
      EMPTY.pipe(
        map(data => new Load<%= classify(name) %>sSuccess({ data })),
        catchError(error => of(new Load<%= classify(name) %>sFailure({ error }))))
    )
  )<% if (effectCreator) { %>)<% }%>;
<% } %><% if (feature && !api) { %>
  <% if (!effectCreator) { %>@Effect()<% }%>
  <%= effectMethod %>
    ofType(<%= classify(name) %>ActionTypes.Load<%= classify(name) %>s),
    /** An EMPTY observable only emits completion. Replace with your own observable API request */
    concatMap(() => EMPTY)
  )<% if (effectCreator) { %>)<% }%>;
<% } %>
<% if (feature) { %>  constructor(private actions$: Actions<<%= classify(name) %>Actions>) {}<% } else { %>  constructor(private actions$: Actions) {}<% } %>
}

@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 10, 2019

Preview docs changes for 80ece49 at https://previews.ngrx.io/pr1725-80ece49/

@itayod itayod force-pushed the feature/effect-creator-schematics branch from 80ece49 to 137eb71 Compare April 11, 2019 15:15
@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 11, 2019

Preview docs changes for 137eb71 at https://previews.ngrx.io/pr1725-137eb71/

@itayod itayod force-pushed the feature/effect-creator-schematics branch from 137eb71 to c0f85cd Compare April 11, 2019 15:24
@itayod
Copy link
Contributor Author

itayod commented Apr 11, 2019

I have updated the code.
just one nit, what do you think about using ts compiler instead regex for the tests?

@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 11, 2019

Preview docs changes for c0f85cd at https://previews.ngrx.io/pr1725-c0f85cd/

Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was a tidbit too fast 😅

Should we also add a test to check createEffect isn't used when we don't use the -c flag?

const effectName = stringUtils.classify(name);
return effectCreator
? `load${effectName}s$ = createEffect(() => this.actions$.pipe(`
: '@Effect()\n' + `\tload${effectName}s$ = this.actions$.pipe(`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tab here isn't needed, currently it will output:

  @Effect()
        loadFoos$ = this.actions$.pipe(
    ofType(FooActionTypes.LoadFoos),
    /** An EMPTY observable only emits completion. Replace with your own observable API request */
    concatMap(() => EMPTY)
  );

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm weird when I test it I am getting different result 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apparently because I use tab as 2 spaces in my pc it looked good...
thanks for your notice!! :)

@timdeschryver
Copy link
Member

just one nit, what do you think about using ts compiler instead regex for the tests?

Not sure what you mean, how would a ts compiler test look like?

modules/schematics/src/effect/schema.json Outdated Show resolved Hide resolved
modules/schematics/src/effect/schema.ts Show resolved Hide resolved
modules/schematics/src/feature/schema.ts Outdated Show resolved Hide resolved
modules/schematics/src/effect/schema.ts Outdated Show resolved Hide resolved
@itayod
Copy link
Contributor Author

itayod commented Apr 11, 2019

just one nit, what do you think about using ts compiler instead regex for the tests?

Not sure what you mean, how would a ts compiler test look like?

Well, I mean use ts compiler to test if the template has the expected result.
I have created a quick function to demonstrate how:

function getImportSpecifiersFor(file: ts.Node, importName: string) {
  let imports;
  file.forEachChild((node) => {
    if (ts.isImportDeclaration(node)
        && node.moduleSpecifier.text === importName
        && node.importClause) {
      imports = (node.importClause.namedBindings as NamedImports).elements
          .map((importElem) => importElem.name.text)
    }
  })
}

and then the test looks:

    const importsFromNgrx = getImportSpecifiersFor(file, '@ngrx/effects');
    expect(importsFromNgrx).toEqual([ 'Actions', 'createEffect', 'ofType' ]);

@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 11, 2019

Preview docs changes for b44e3cc at https://previews.ngrx.io/pr1725-b44e3cc/

@@ -316,4 +317,42 @@ describe('Effect Schematic', () => {
/constructor\(private actions\$: Actions<FooActions>\) {}/
);
});

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const options = { ...defaultOptions, effectCreator: true, feature: true };
const options = { ...defaultOptions, effectCreators: true, feature: true };

it('should create an api effect using creator function', () => {
const options = {
...defaultOptions,
effectCreator: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
effectCreator: true,
effectCreators: true,

/**
* Specifies if the effect creation uses 'createEffect'
*/
effectCreator?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
effectCreator?: boolean;
effectCreators?: boolean;

@itayod itayod force-pushed the feature/effect-creator-schematics branch from b44e3cc to 518f6e9 Compare April 12, 2019 14:02
@ngrxbot
Copy link
Collaborator

ngrxbot commented Apr 12, 2019

Preview docs changes for 518f6e9 at https://previews.ngrx.io/pr1725-518f6e9/

@brandonroberts brandonroberts merged commit 8901abd into ngrx:master Apr 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Schematics: Add schematics for effect creators
4 participants