import { HttpClient, HttpEvent, HttpParams } from '@angular/common/http'; import { Injector } from '@angular/core'; import { Observable } from 'rxjs'; import { CustomHttpUrlEncodingCodec, HeadersConfiguration, List, RequiredParam, Validate } from '../utils'; import { map, tap } from 'rxjs/operators'; const ROOT_CHANGES_KEY = 'root'; export interface HeaderOptions { readonly authorization?: boolean; readonly accept?: boolean; readonly contentType?: boolean; } export interface QueryParam { readonly key: string; readonly value: string | number | boolean; } /** * I for interface * R for response */ export abstract class GenericService { protected readonly _http = this._injector.get(HttpClient); protected readonly _lastCheckedForChanges = new Map([[ROOT_CHANGES_KEY, '0']]); protected constructor(protected readonly _injector: Injector, protected readonly _defaultModelPath: string) {} get(): Observable; // eslint-disable-next-line @typescript-eslint/unified-signatures get(id: string, ...args: unknown[]): Observable; // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars get(id?: string, ...args: unknown[]): Observable { return id ? this._getOne([id]) : this.getAll(); } getAll(modelPath = this._defaultModelPath, queryParams?: List): Observable { return this._http .get(`/${encodeURI(modelPath)}`, { headers: HeadersConfiguration.getHeaders({ contentType: false }), observe: 'body', params: this._queryParams(queryParams), }) .pipe(tap(() => this._updateLastChanged())); } getFor(entityId: string, queryParams?: List): Observable { return this.getAll(`${this._defaultModelPath}/${entityId}`, queryParams).pipe(tap(() => this._updateLastChanged(entityId))); } @Validate() delete(@RequiredParam() body: unknown, modelPath = this._defaultModelPath, queryParams?: List): Observable { let path = `/${encodeURI(modelPath)}`; if (typeof body === 'string') { path += `/${encodeURIComponent(body)}`; } return this._http.delete(path, { body: body, params: this._queryParams(queryParams), headers: HeadersConfiguration.getHeaders({ contentType: false }), observe: 'body', }); } @Validate() upload(data?: Blob, modelPath = this._defaultModelPath): Observable> { const formParams = new FormData(); if (data !== undefined) { formParams.append('file', data); } const headers = HeadersConfiguration.getHeaders({ contentType: false }); return this._http.post(`/${encodeURI(modelPath)}`, formParams, { headers, observe: 'events', reportProgress: true, }); } hasChanges$(key = ROOT_CHANGES_KEY): Observable { const modelPath = key === ROOT_CHANGES_KEY ? '' : `${key}/`; const body = { value: this._lastCheckedForChanges.get(key) ?? '0' }; return this._post<{ value: boolean }>(body, `${this._defaultModelPath}/${modelPath}changes`).pipe( map((res: { value: boolean }) => res.value), ); } @Validate() protected _post( @RequiredParam() body: unknown, modelPath = this._defaultModelPath, queryParams?: List, ): Observable { return this._http.post(`/${encodeURI(modelPath)}`, body, { params: this._queryParams(queryParams), headers: HeadersConfiguration.getHeaders(), observe: 'body', }); } @Validate() protected _put( @RequiredParam() body: unknown, modelPath = this._defaultModelPath, queryParams?: List, ): Observable { return this._http.put(`/${encodeURI(modelPath)}`, body, { params: this._queryParams(queryParams), headers: HeadersConfiguration.getHeaders(), observe: 'body', }); } @Validate() protected _getOne( @RequiredParam() path: List, modelPath = this._defaultModelPath, queryParams?: List, ): Observable { const entityPath = path.map(item => encodeURIComponent(item)).join('/'); return this._http.get(`/${encodeURI(modelPath)}/${entityPath}`, { headers: HeadersConfiguration.getHeaders({ contentType: false }), params: this._queryParams(queryParams), observe: 'body', }); } protected _queryParams(queryParams?: List): HttpParams { let queryParameters = new HttpParams({ encoder: new CustomHttpUrlEncodingCodec() }); queryParams?.forEach(param => { if (param?.value !== undefined && param?.value !== null) { queryParameters = queryParameters.append(param.key, param.value); } }); return queryParameters; } protected _updateLastChanged(key = ROOT_CHANGES_KEY): void { this._lastCheckedForChanges.set(key, new Date().toISOString()); } }