UNPKG

first-npm-package-nicule

Version:

This isi first npm package

102 lines (85 loc) 4 kB
import { Observable } from 'rxjs'; import { ProgressTracker } from './progress-tracker'; import { Hypermedia, HypermediaAction, HypermediaField } from '../interfaces'; import { SessionService } from '@core/services'; import { Injectable, Type } from '@angular/core'; import { HeaderProvider } from './header-provider'; // import { ReflectiveModelBinderFactory } from 'hypermedia/models/services/reflective-model-binder'; // import { ReflectiveQueryMatcherFactory } from 'hypermedia/models/services/reflective-query-matcher'; import { filter, map, catchError } from 'rxjs/operators'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { ReflectiveModelBinderFactory } from '../../models/services/reflective-model-binder'; import { ReflectiveQueryMatcherFactory } from '../../models/services/reflective-query-matcher'; @Injectable() export class ActionExecutor { private readonly fakeResponse = { 500: { class: ['error'], properties: { msg: 'error.message.internalServerError' } } }; constructor(private http: HttpClient, private modelBinderFactory: ReflectiveModelBinderFactory, private progressTracker: ProgressTracker, private headerProvider: HeaderProvider, private queryMatcherFactory: ReflectiveQueryMatcherFactory, private sessionService: SessionService) { } execute(action: HypermediaAction, fieldValues?: any, authorize: boolean = true, tokenOverride?: string): Observable<Hypermedia> { const fields = this.computeActionFields(action.fields, fieldValues); return this.http.request(action.method, action.href, { body: { name: action.name, fields }, headers: this.headerProvider.getHeaders(authorize, tokenOverride), reportProgress: true }).pipe( map(response => this.computeHypermediaResponse(response)), catchError(error => this.handleActionErrors(error)) ); } executeAs<T>(action: HypermediaAction, type: Type<T>, fieldValues?: any, authorize: boolean = true): Observable<T> { const modelBinder = this.modelBinderFactory.make(type); const queryMatcher = this.queryMatcherFactory.make(type); return this.execute(action, fieldValues, authorize) .pipe( filter(response => queryMatcher.matches(response)), map(response => modelBinder.bind(response)) ) } computeHypermediaResponse(response: Response | any): Hypermedia { try { return response as Hypermedia; } catch (err) { return { class: ['no-content'] } as Hypermedia; } } computeActionFields(fields: Array<HypermediaField> = [], overrides: any = {}): any { const fieldValues = fields.reduce((acc, { name, value }) => ({ ...acc, [name]: value }), {}); return { ...fieldValues, ...overrides }; } private handleActionErrors(responseError: HttpErrorResponse): Array<Hypermedia> { if (!(responseError instanceof HttpErrorResponse)) { return []; } const { status } = responseError; const responseData = responseError.error; const { class: classes } = responseData; if (status === 401) { this.intercept401(classes); } if (classes instanceof Array) { // if it's a valid hypermedia, emit on error return [responseData]; } return [this.fakeResponse[status]]; } private intercept401(classes: Array<string>): void { const requiredClasses = ['external', 'redirect', 'unauthorized']; if (requiredClasses.every(requiredClass => classes.includes(requiredClass))) { this.sessionService.renew(); } } }