@starsched/sdk
Version:
ABA clinic control and management service API SDK
154 lines (153 loc) • 5.23 kB
JavaScript
export class HttpClient {
baseURL;
requestInterceptors;
responseInterceptors;
constructor(options) {
this.baseURL = options?.baseURL;
this.requestInterceptors = options?.requestInterceptors ?? [];
this.responseInterceptors = options?.responseInterceptors ?? [];
}
mountHeaders(headers) {
return new Headers({
Accept: 'application/json',
'Content-Type': 'application/json',
...headers
});
}
async extractBodyJsonFromResponse(response) {
const responseContentType = response.headers.get('Content-Type');
const isJsonResponse = responseContentType?.includes('application/json') ?? false;
let body = null;
if (isJsonResponse) {
body = await response.json();
}
return body;
}
async initRequest(request) {
const config = {
method: request.method,
url: request.url,
queryParams: request.queryParams,
headers: this.mountHeaders(request.headers),
mode: 'cors',
signal: request.abortSignal
};
if (!request.body) {
config.headers.delete('Content-Type');
}
const requestContentType = config.headers.get('Content-Type');
const isJsonBody = requestContentType?.startsWith('application/json') ?? false;
if (request.body && isJsonBody) {
config.body = JSON.stringify(request.body);
}
return this.request(config);
}
isHttpResponse(maybeHttpResponse) {
return (typeof maybeHttpResponse === 'object' &&
maybeHttpResponse !== null &&
'ok' in maybeHttpResponse &&
'statusCode' in maybeHttpResponse);
}
async request(config) {
let configCopy = config;
const url = new URL(configCopy.url, this.baseURL);
const queryParamsEntires = Object.entries(configCopy.queryParams ?? {});
for (const [name, value] of queryParamsEntires) {
url.searchParams.append(name, String(value));
}
try {
/** Intercepta a requisição antes de ela ser executada */
for (const interceptor of this.requestInterceptors) {
configCopy = await interceptor(configCopy);
}
const response = await fetch(url, configCopy);
const responseBody = await this.extractBodyJsonFromResponse(response);
let httpResponse = {
ok: response.ok,
statusCode: response.status,
headers: response.headers,
body: responseBody
};
/** Intercepta a resposta antes de devolver */
for (const interceptor of this.responseInterceptors) {
httpResponse = (await interceptor(configCopy, httpResponse));
}
return httpResponse;
}
catch (error) {
if (this.isHttpResponse(error)) {
return error;
}
if (error instanceof Error) {
if (error.name === 'ConnectionRefused') {
// TODO: Atribuir uma mensagem diferente
}
if (error.name === 'Timeout') {
// TODO: Implementar timeout e atribuir uma mensagem diferente
}
}
return {
ok: false,
headers: {},
statusCode: 0,
body: {
code: 'internal',
message: 'We are unable to process your request right now, please try again later.'
}
};
}
}
get(url, options) {
const request = {
method: 'GET',
url,
headers: options?.headers,
queryParams: options?.queryParams,
abortSignal: options?.abortSignal
};
return this.initRequest(request);
}
post(url, body, options) {
const request = {
method: 'POST',
url,
headers: options?.headers,
queryParams: options?.queryParams,
body,
abortSignal: options?.abortSignal
};
return this.initRequest(request);
}
put(url, body, options) {
const request = {
method: 'PUT',
url,
headers: options?.headers,
queryParams: options?.queryParams,
body,
abortSignal: options?.abortSignal
};
return this.initRequest(request);
}
patch(url, body, options) {
const request = {
method: 'PATCH',
url,
headers: options?.headers,
queryParams: options?.queryParams,
body,
abortSignal: options?.abortSignal
};
return this.initRequest(request);
}
delete(url, options) {
const request = {
method: 'DELETE',
url,
headers: options?.headers,
queryParams: options?.queryParams,
abortSignal: options?.abortSignal
};
return this.initRequest(request);
}
}