@uprtcl/http-provider
Version:
_Prtcl provider wrappers around the native fetch api
162 lines (138 loc) • 4.56 kB
text/typescript
import { Logger } from '@uprtcl/evees';
import { HttpAuthentication } from './auth/http.authentication';
import { AuthTokenStorage } from './auth/http.token.store';
import { HttpAuthenticatedConnection } from './http.auth.connection.if';
import { GetResult, PostResult } from './http.connection';
const LOG = false;
/** Exposes wrappers to FETCH methods, and injects the header authentication
* credentials (provided by HttpAuthentication service) */
export class HttpAuthenticatedConnectionImp implements HttpAuthenticatedConnection {
logger = new Logger('HTTP CONNECTION');
tokenStore!: AuthTokenStorage;
constructor(
readonly host: string,
protected authentication?: HttpAuthentication,
tokenStorageId?: string,
userStorageId?: string
) {
if (tokenStorageId && userStorageId) {
this.tokenStore = new AuthTokenStorage(tokenStorageId, userStorageId);
}
}
get userId() {
return this.tokenStore.userId;
}
async login() {
if (!this.authentication) throw new Error('Authentication service not defined');
const token = await this.authentication.obtainToken();
if (token.jwt && token.userId) {
this.tokenStore.authToken = 'Bearer ' + token.jwt;
this.tokenStore.userId = token.userId;
const isValid = await this.get('/user/isAuthorized');
if (!isValid) {
this.logout();
}
}
}
async connect(): Promise<void> {}
async isConnected(): Promise<boolean> {
return true;
}
async disconnect(): Promise<void> {}
async isLogged(): Promise<boolean> {
return this.userId !== undefined;
}
async logout(): Promise<void> {
this.tokenStore.userId = undefined;
this.tokenStore.authToken = undefined;
}
get headers(): HeadersInit {
const headers: HeadersInit = {
'Content-Type': 'application/json',
};
if (this.tokenStore && this.tokenStore.authToken) {
headers['Authorization'] = this.tokenStore.authToken;
}
return headers;
}
public async get<T>(url: string): Promise<T> {
if (LOG) this.logger.log('[HTTP GET]: ', url);
return fetch(this.host + url, {
method: 'GET',
headers: this.headers,
})
.then((response) => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json() as Promise<GetResult<T>>;
})
.then((getResult) => {
if (LOG) this.logger.log('[HTTP GET RESULT] ', url, getResult);
if (getResult.result === 'error') {
throw new Error(`Error fetching url: ${url}`);
}
return getResult.data;
});
}
public async getWithPut<T>(url: string, body: any): Promise<T> {
if (LOG) this.logger.log('PUT: ', url);
return fetch(this.host + url, {
method: 'PUT',
headers: this.headers,
body: JSON.stringify(body),
})
.then((response) => {
if (!response.ok) {
throw new Error(response.statusText);
}
return response.json() as Promise<{ data: T }>;
})
.then((data) => {
if (LOG) this.logger.log('[HTTP PUT RESULT] ', url, data);
return data.data;
});
}
public async put(url: string, body: any): Promise<PostResult> {
return this.putOrPost(url, body, 'PUT');
}
public async post(url: string, body: any): Promise<PostResult> {
return this.putOrPost(url, body, 'POST');
}
public async delete(url: string, body: any = {}): Promise<PostResult> {
if (LOG) this.logger.log('[HTTP DELETE]', this.host + url);
return fetch(url, {
method: 'DELETE',
headers: {
...this.headers,
Accept: 'application/json',
},
body: JSON.stringify(body),
})
.then((response) => {
return response.json() as Promise<PostResult>;
})
.then((data) => {
if (LOG) this.logger.log('[HTTP POST RESULT]', url, data);
return (data as unknown) as PostResult;
});
}
public async putOrPost(url: string, body: any, method: string): Promise<PostResult> {
if (LOG) this.logger.log(`[HTTP ${method}]`, url, body);
return fetch(this.host + url, {
method: method,
headers: {
...this.headers,
Accept: 'application/json',
},
body: JSON.stringify(body),
})
.then((response) => {
return response.json() as Promise<PostResult>;
})
.then((data) => {
if (LOG) this.logger.log('[HTTP POST RESULT]', url, body, data);
return (data as unknown) as PostResult;
});
}
}