cloudfoundry-incubator/stratos

View on GitHub
src/frontend/packages/git/src/store/git.effects.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { catchError, mergeMap } from 'rxjs/operators';

import { AppState } from '../../../store/src/app-state';
import { entityCatalog, NormalizedResponse, WrapperRequestActionSuccess } from '../../../store/src/public-api';
import { EntityRequestAction, StartRequestAction, WrapperRequestActionFailed } from '../../../store/src/types/request.types';
import { GitCommit } from '../public_api';
import {
  FetchBranchesForProject,
  FetchBranchForProject,
  FetchCommit,
  FetchCommits,
  FetchGitHubRepoInfo,
} from './git.actions';
import {
  FETCH_BRANCH_FOR_PROJECT,
  FETCH_BRANCHES_FOR_PROJECT,
  FETCH_COMMIT,
  FETCH_COMMITS,
  FETCH_GITHUB_REPO,
} from './git.public-types';


// FIXME: This should be removed in favour of entity action builder config.
// See github commit action builder for an example,
// https://github.com/cloudfoundry-incubator/stratos/issues/3770
@Injectable()
export class GitEffects {
  constructor(
    private actions$: Actions,
    private store: Store<AppState>,
    private httpClient: HttpClient
  ) { }

  @Effect()
  fetchRep$ = this.actions$.pipe(
    ofType<FetchGitHubRepoInfo>(FETCH_GITHUB_REPO),
    mergeMap(action => {
      const actionType = 'fetch';
      this.store.dispatch(new StartRequestAction(action, actionType));
      const entityConfig = entityCatalog.getEntity(action);
      return action.meta.scm.getRepository(this.httpClient, action.meta.projectName).pipe(
        mergeMap(repoDetails => {
          const mappedData: NormalizedResponse = {
            entities: { [entityConfig.entityKey]: {} },
            result: []
          };
          repoDetails.scmType = action.meta.scm.getType();
          repoDetails.projectName = action.meta.projectName;
          repoDetails.guid = action.guid;
          repoDetails.endpointGuid = action.meta.scm.endpointGuid;
          mappedData.entities[entityConfig.entityKey][repoDetails.guid] = repoDetails;
          mappedData.result.push(repoDetails.guid);
          return [
            new WrapperRequestActionSuccess(mappedData, action, actionType)
          ];
        }),
        catchError(err => [
          new WrapperRequestActionFailed(action.meta.scm.parseErrorAsString(err), action, actionType)
        ]
        ));
    }));

  @Effect()
  fetchBranches$ = this.actions$.pipe(
    ofType<FetchBranchesForProject>(FETCH_BRANCHES_FOR_PROJECT),
    mergeMap(action => {
      const actionType = 'fetch';
      this.store.dispatch(new StartRequestAction(action, actionType));
      return action.scm.getBranches(this.httpClient, action.projectName).pipe(
        mergeMap(branches => {
          const entityKey = entityCatalog.getEntity(action).entityKey;
          const mappedData: NormalizedResponse = {
            entities: { [entityKey]: {} },
            result: []
          };

          branches.forEach(b => {
            b.scmType = action.scm.getType();
            b.projectName = action.projectName;
            b.guid = action.entity[0].getId(b);
            b.endpointGuid = action.scm.endpointGuid;
            mappedData.entities[entityKey][b.guid] = b;
            mappedData.result.push(b.guid);
          });
          return [
            new WrapperRequestActionSuccess(mappedData, action, actionType)
          ];
        }),
        catchError(err => [
          new WrapperRequestActionFailed(action.scm.parseErrorAsString(err), action, actionType)
        ]));
    }));

  @Effect()
  fetchBranch$ = this.actions$.pipe(
    ofType<FetchBranchForProject>(FETCH_BRANCH_FOR_PROJECT),
    mergeMap(action => {
      const actionType = 'fetch';
      this.store.dispatch(new StartRequestAction(action, actionType));
      return action.scm.getBranch(this.httpClient, action.projectName, action.branchName).pipe(
        mergeMap(branch => {
          const entityKey = entityCatalog.getEntity(action).entityKey;
          const mappedData: NormalizedResponse = {
            entities: { [entityKey]: {} },
            result: []
          };
          branch.scmType = action.scm.getType();
          branch.projectName = action.projectName;
          branch.guid = action.guid;
          branch.endpointGuid = action.scm.endpointGuid;
          mappedData.entities[entityKey][branch.guid] = branch;
          mappedData.result.push(branch.guid);
          return [
            new WrapperRequestActionSuccess(mappedData, action, actionType)
          ];
        }),
        catchError(err => [
          new WrapperRequestActionFailed(action.scm.parseErrorAsString(err), action, actionType)
        ]));
    }));

  @Effect()
  fetchCommit$ = this.actions$.pipe(
    ofType<FetchCommit>(FETCH_COMMIT),
    mergeMap(action => {
      const actionType = 'fetch';
      this.store.dispatch(new StartRequestAction(action, actionType));
      return action.scm.getCommit(this.httpClient, action.projectName, action.commitSha).pipe(
        mergeMap(commit => {
          const entityKey = entityCatalog.getEntity(action).entityKey;
          const mappedData: NormalizedResponse = {
            entities: { [entityKey]: {} },
            result: []
          };
          this.addCommit(
            entityKey,
            mappedData,
            this.updateCommit(action.scm.getType(), action.projectName, commit, action.scm.endpointGuid, action)
          );
          return [
            new WrapperRequestActionSuccess(mappedData, action, actionType)
          ];
        }),
        catchError(err => [
          new WrapperRequestActionFailed(action.scm.parseErrorAsString(err), action, actionType)
        ]));
    }));

  @Effect()
  fetchCommits$ = this.actions$.pipe(
    ofType<FetchCommits>(FETCH_COMMITS),
    mergeMap(action => {
      const actionType = 'fetch';
      this.store.dispatch(new StartRequestAction(action, actionType));
      return action.scm.getCommits(this.httpClient, action.projectName, action.sha).pipe(
        mergeMap((commits: GitCommit[]) => {
          const entityKey = entityCatalog.getEntity(action).entityKey;
          const mappedData: NormalizedResponse = {
            entities: { [entityKey]: {} },
            result: []
          };
          commits.forEach(commit => {
            this.addCommit(entityKey, mappedData, this.updateCommit(action.scm.getType(),
              action.projectName,
              commit,
              action.scm.endpointGuid,
              action
            ));
          });
          return [
            new WrapperRequestActionSuccess(mappedData, action, actionType)
          ];
        }),
        catchError(err => [
          new WrapperRequestActionFailed(action.scm.parseErrorAsString(err), action, actionType)
        ]));
    }));

  updateCommit(scmType: string, projectName: string, commit: GitCommit, endpointGuid: string, action: EntityRequestAction): GitCommit {
    const newCommit = {
      ...commit,
      scmType,
      projectName,
      endpointGuid,
    };
    newCommit.guid = action.entity[0].getId(newCommit);

    return newCommit;
  }

  addCommit(entityKey: string, mappedData: NormalizedResponse, commit: GitCommit) {
    mappedData.entities[entityKey][commit.guid] = commit;
    mappedData.result.push(commit.guid);
  }

}