@rxap/remote-method
Version:
This package provides abstractions for defining and executing remote methods in Angular applications. It includes features such as automatic refreshing, proxying, and error handling. It offers a structured way to manage remote calls and their dependencies
170 lines (163 loc) • 8.25 kB
JavaScript
import * as i0 from '@angular/core';
import { Injector, Injectable, Inject, Optional } from '@angular/core';
import * as i1 from '@angular/common/http';
import { HttpClient, HttpRequest, HttpEventType, HttpResponse } from '@angular/common/http';
import * as i1$1 from '@rxap/remote-method';
import { BaseRemoteMethod, RxapRemoteMethodError, REMOTE_METHOD_META_DATA, RemoteMethodLoader } from '@rxap/remote-method';
import { hasIndexSignature } from '@rxap/utilities';
import { retry, tap, filter, map, timeout } from 'rxjs/operators';
import { firstValueFrom } from 'rxjs';
class BaseHttpRemoteMethod extends BaseRemoteMethod {
constructor(http, injector, metaData = null) {
super(injector, metaData);
this.http = http;
this.timeout = 60 * 1000;
this.timeout = this.metadata.timeout ?? this.timeout;
if (http === undefined) {
throw new RxapRemoteMethodError('HttpClient is undefined. Ensure that the HttpClient is added to the deps property!', '', this.constructor.name);
}
if (!(http instanceof HttpClient)) {
throw new RxapRemoteMethodError('The property http is not an instance of HttpClinent. Check the deps property!', '', this.constructor.name);
}
}
init() {
super.init();
this._httpRequest = new HttpRequest(this.metadata.method, this.getRequestUrl(), null, {
headers: this.metadata.headers,
reportProgress: this.metadata.reportProgress,
params: this.metadata.params,
responseType: this.metadata.responseType || 'json',
withCredentials: this.metadata.withCredentials,
});
}
updateRequest(parameters) {
let url = this._httpRequest.url;
if (parameters && parameters['pathParams']) {
url = this.buildUrlWithParams(url, parameters.pathParams);
}
return this._httpRequest.clone({
withCredentials: this.metadata.withCredentials,
...parameters,
url,
});
}
buildUrlWithParams(url, pathParams) {
if (pathParams) {
if (!hasIndexSignature(pathParams)) {
throw new RxapRemoteMethodError(`Path params for remote method '${this.id}' has not an index signature`, '', this.constructor.name);
}
const matches = url.match(/\{[^}]+\}/g);
if (matches) {
for (const match of matches) {
const param = match.substr(1, match.length - 2);
if (pathParams[param] === undefined) {
throw new RxapRemoteMethodError(`Path params for remote method '${this.id}' has not a defined value for '${param}'`, '', this.constructor.name);
}
url = url.replace(match, encodeURIComponent(pathParams[param]));
}
}
}
return url;
}
getRequestUrl() {
if (typeof this.metadata.url === 'function') {
return this.metadata.url();
}
return this.metadata.url;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseHttpRemoteMethod, deps: [{ token: HttpClient }, { token: Injector }, { token: REMOTE_METHOD_META_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseHttpRemoteMethod }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: BaseHttpRemoteMethod, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpClient, decorators: [{
type: Inject,
args: [HttpClient]
}] }, { type: i0.Injector, decorators: [{
type: Inject,
args: [Injector]
}] }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [REMOTE_METHOD_META_DATA]
}] }] });
class HttpRemoteMethod extends BaseHttpRemoteMethod {
// eslint-disable-next-line @typescript-eslint/no-empty-function
onSentEvent(event) {
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onHeaderResponse(event) {
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onResponse(event) {
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
onProgressEvent(event) {
}
// TODO : make abstract to force implementation to handel parameter transformation
createHttpRequestParameters(parameters) {
return parameters ?? {};
}
transformer(response) {
return response;
}
_call(parameters) {
return firstValueFrom(this.http.request(this.updateRequest(this.createHttpRequestParameters(parameters)))
.pipe(retry(this.metadata.retry ?? 0), tap(event => {
switch (event.type) {
case HttpEventType.Sent:
this.onSentEvent(event);
break;
case HttpEventType.Response:
this.onResponse(event);
break;
case HttpEventType.DownloadProgress:
this.onProgressEvent(event);
break;
case HttpEventType.UploadProgress:
this.onProgressEvent(event);
break;
case HttpEventType.ResponseHeader:
this.onHeaderResponse(event);
break;
}
}), filter((event) => event instanceof HttpResponse), map((event) => event.body), map(body => this.transformer(body)), timeout(this.timeout)));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethod, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethod }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethod, decorators: [{
type: Injectable
}] });
class HttpRemoteMethodLoader {
// Instead of extanding the RemoteMethodLoader class the RemoteMethodLoader instance
// will be injected, else there could be multiple instance of RemoteMethodLoader's. Then
// the RefreshService will not trigger a refresh for HttpRemoteMethod's
constructor(remoteMethodLoader) {
this.remoteMethodLoader = remoteMethodLoader;
}
request$(remoteMethodIdOrInstanceOrToken, parameters, metadata, injector, notFoundValue, flags) {
const remoteMethod = this.remoteMethodLoader.load(remoteMethodIdOrInstanceOrToken, metadata, injector, notFoundValue, flags);
if (!(remoteMethod instanceof HttpRemoteMethod)) {
throw new RxapRemoteMethodError(`The remote method is not a HttpRemoteMethod`, '', 'HttpRemoteMethodLoader');
}
return remoteMethod.call(parameters);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethodLoader, deps: [{ token: RemoteMethodLoader }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethodLoader, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: HttpRemoteMethodLoader, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [{ type: i1$1.RemoteMethodLoader, decorators: [{
type: Inject,
args: [RemoteMethodLoader]
}] }] });
// region
// endregion
/**
* Generated bundle index. Do not edit.
*/
export { BaseHttpRemoteMethod, HttpRemoteMethod, HttpRemoteMethodLoader };
//# sourceMappingURL=rxap-remote-method-http.mjs.map