first-npm-package-nicule
Version:
This isi first npm package
97 lines (82 loc) • 3.78 kB
text/typescript
import { throwError as observableThrowError, Observable, timer, of } from 'rxjs';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Router } from '@angular/router';
// import { Response } from '@angular/http';
import { AppState } from 'app/app.state';
import { Store } from '@ngrx/store';
import { UpdateProgress } from '@core/actions/progress.actions';
import { ResourceFetcher } from '../services';
import { FetchHypermedia, HypermediaActionTypes, ReceivedHypermedia } from '../actions';
import { Hypermedia } from '../interfaces';
import { Injectable } from '@angular/core';
import { mapTo, flatMap, finalize, retryWhen, catchError, map, take } from 'rxjs/operators';
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
()
export class HypermediaEffects {
private readonly statusCodeMessages = {
0: 'disconnected',
400: 'badRequest',
404: 'notFound',
403: 'forbidden',
409: 'conflict',
503: 'serviceUnavailable',
500: 'internalServerError'
};
constructor(private actions: Actions,
private store: Store<AppState>,
private hypermedia: ResourceFetcher,
private router: Router) { }
()
fetchHypermedia = this.actions
.pipe(
ofType(HypermediaActionTypes.FETCH_HYPERMEDIA),
flatMap(({ payload }: FetchHypermedia) =>
of(0).pipe(// new observable to be retried
flatMap(_ =>
this.hypermedia
.get(payload.path, payload.scope, payload.authorize, payload.tokenOverride)
),
finalize(() => this.store.dispatch(new UpdateProgress(undefined))),
retryWhen(errors => errors.pipe(
flatMap(error => {
if (error.status === 401) { // retry on 401 status code, after 1000 seconds
return timer(1000).pipe(mapTo(error));
}
return observableThrowError(error);
}),
take(3) // 3 times
)),
catchError(error => {
return this.applyInterceptors(payload.interceptors, error)
}),
catchError(error => {
return this.handleResourceErrors(error);
}),
map(hypermedia => new ReceivedHypermedia({
path: payload.path,
scope: payload.scope,
authorize: payload.authorize,
hypermedia: { ...hypermedia, source: { ...payload, receivedAt: Date.now() } }
})))
)
)
private handleResourceErrors(response: HttpErrorResponse): Array<Hypermedia> {
if (!(response instanceof HttpErrorResponse)) {
return [];
}
if (response.status in this.statusCodeMessages) {
if (response.error && response.error.class && response.error.class.includes('not-redirect')) {
return [response.error];
}
this.router.navigate(['error', this.statusCodeMessages[response.status]]);
}
return [response.error];
}
applyInterceptors(interceptors: any, httpErrorResponse: HttpErrorResponse): Array<any> {
if (interceptors[httpErrorResponse.status]) {
interceptors[httpErrorResponse.status](httpErrorResponse.error);
return [];
}
throw httpErrorResponse;
}
}