Skip to content

Instantly share code, notes, and snippets.

@UmerIftikhar
Last active September 6, 2020 12:26
Show Gist options
  • Select an option

  • Save UmerIftikhar/e87b8a5b82342bac099e74c1c9901b2f to your computer and use it in GitHub Desktop.

Select an option

Save UmerIftikhar/e87b8a5b82342bac099e74c1c9901b2f to your computer and use it in GitHub Desktop.
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import urljoin from 'url-join';
import { catchError } from 'rxjs/operators';
/*
This should be placed in some miscellaneous folder.
*/
export function constructApiVersionQueryParams(inputParams: HttpParams, apiVersion: string): HttpParams {
if (inputParams && inputParams.keys().length > 0) {
inputParams = inputParams.append('apiVersion', apiVersion);
return inputParams;
}
const params = new HttpParams().set('version', apiVersion);
return params;
}
/*
This should be placed in some folder contatining interface definitions.
*/
export interface HttpOptions {
headers?:
| HttpHeaders
| {
[header: string]: string | string[];
};
observe?: any;
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}
/*
This should be placed in some file containing all the application constants.
*/
export class Constants {
public static apiRoot = '/api', // If there is some prefix for all the APIs, then define that in constants.
public static API_VERSIONS = {
Version1: 'version1',
};
}
/*
Generic Service.
It assume that all the apis being called are versioned via query parameter, so the endpoint will look some thing like:
http://localhost:3000/todoItem?version=1
http://localhost:3000/todoItem/1?version=1
*/
export abstract class BaseService<TRead, TCreate, TUpdate> {
private endpointUrl: string;
constructor(private readonly http: HttpClient, private readonly path: string) {
this.endpointUrl = urljoin(Constants.apiRoot, this.path);
}
protected formatErrors(error: any) {
return throwError(error.error);
}
get(apiVersion: string, options: HttpOptions = {}): Observable<TRead[]> {
options.params = constructApiVersionQueryParams(options.params, apiVersion.toString());
return this.http.get<TRead[]>(this.endpointUrl, options).pipe(catchError(this.formatErrors));
}
getById(apiVersion: string, id: string, options: HttpOptions = {}): Observable<TRead> {
options.params = constructApiVersionQueryParams(options.params, apiVersion.toString());
const url = urljoin(this.endpointUrl, id);
return this.http.get<TRead>(url, options).pipe(catchError(this.formatErrors));
}
create(apiVersion: string, creationBody: TCreate, options: HttpOptions = {}): Observable<TRead> {
options.params = constructApiVersionQueryParams(options.params, apiVersion.toString());
return this.http.post<TRead>(this.endpointUrl, creationBody, options).pipe(catchError(this.formatErrors));
}
update(apiVersion: string, id: string, updateBody: TUpdate, options: HttpOptions = {}): Observable<any> {
options.params = constructApiVersionQueryParams(options.params, apiVersion.toString());
const url = urljoin(this.endpointUrl, id);
return this.http.put(url, updateBody, options).pipe(catchError(this.formatErrors));
}
delete(apiVersion: string, id: string, options: HttpOptions = {}): Observable<any> {
options.params = constructApiVersionQueryParams(options.params, apiVersion.toString());
const url = urljoin(this.endpointUrl, id);
return this.http.delete(url, options).pipe(catchError(this.formatErrors));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment