@smash-sdk/core
Version:
Smash Sdk Core
151 lines (150 loc) • 5.75 kB
JavaScript
import { config } from '../config/config';
import { InvalidHostError, InvalidRegionError, InvalidRegionOrHostError, UnknownError } from '../errors/sdkError';
import { formatErrorName } from '../helper/error';
import { isNode } from '../helper/node';
import { RefreshTokenManager } from '../helper/refreshTokenManager';
import { AxiosClient } from '../http';
export class Client {
constructor(params) {
this.service = params.service;
this.client = params.client || new AxiosClient();
this.client.setHttpConfiguration({
timeout: this.getTimeout(params),
httpAgent: params.httpAgent,
httpsAgent: params.httpsAgent,
});
this.token = params.token ? params.token : config.getToken();
this.region = this.getRegion(params);
this.host = this.getHost(params);
this.userAgent = params.userAgent;
if (params.refreshTokenMethod) {
this.refreshTokenManager = new RefreshTokenManager(params.refreshTokenMethod);
this.refreshTokenMethod = this.refreshTokenManager.getRefreshTokenMethod();
}
else if (config.getRefreshTokenMethod() && config.getRefreshTokenManager() !== undefined) {
this.refreshTokenManager = config.getRefreshTokenManager();
this.refreshTokenMethod = this.refreshTokenManager?.getRefreshTokenMethod();
}
}
getRegion(params) {
const region = config.getRegion();
if (params.type === 'global' && params.region) {
throw new InvalidRegionError('Invalid region: region ' + params.region + ' provided in constructor not available');
}
if (!params.host && params.type === 'regional' && !params.region && !region) {
throw new InvalidRegionOrHostError('Invalid region or host: no host or no region provided in constructor and no region configured in config');
}
if (params.type === 'global') {
return 'global';
}
if (params.region && params.type === 'regional') {
return params.region;
}
if (region && params.type === 'regional') {
return region;
}
if (!params.host) {
throw new InvalidRegionError('Invalid region: no region provided in constructor and no region configured in config');
}
}
getHost(params) {
if (params.host) {
return params.host;
}
const host = config.getHost(this.service, this.region);
if (host) {
return host;
}
throw new InvalidHostError('Invalid host: no host provided in constructor and no host configured in config');
}
getTimeout(params) {
if (params.timeout) {
return params.timeout;
}
const timeout = config.getTimeout();
if (timeout) {
return timeout;
}
return undefined;
}
getHttpAgent(params) {
if (params.httpAgent) {
return params.httpAgent;
}
const httpAgent = config.getHttpAgent();
if (httpAgent) {
return httpAgent;
}
return undefined;
}
getHttpsAgent(params) {
if (params.httpsAgent) {
return params.httpsAgent;
}
const httpsAgent = config.getHttpsAgent();
if (httpsAgent) {
return httpsAgent;
}
return undefined;
}
handle(request, retries = 0) {
return new Promise(async (resolve, reject) => {
if (isNode()) {
request.headers['User-Agent'] = this.userAgent;
}
request = this.cleanRequest(request);
try {
const smashResponse = await this.client.handle(request);
if (smashResponse.statusCode === 401 && typeof request.refreshTokenMethod === 'function') {
try {
const token = await request.refreshTokenMethod(smashResponse, retries);
if (token) {
this.token = token;
const newRequest = request;
newRequest.headers = { ...request.headers, Authorization: 'Bearer ' + this.token };
const newResponse = await this.handle(newRequest, ++retries);
resolve(newResponse);
}
else {
resolve(smashResponse);
}
}
catch (error) {
reject(error);
}
}
else {
resolve(smashResponse);
}
}
catch (error) {
reject(error);
}
});
}
parseResponse(response, errors) {
if (this.isValidStatusCode(response.statusCode)) {
return response.body ? response.body : {};
}
else if (response?.body?.name && errors[formatErrorName((response?.body).name)]) {
const body = response?.body;
const error = new errors[formatErrorName((response?.body).name)](body);
throw error;
}
else {
throw new UnknownError(response?.body);
}
}
isValidStatusCode(code) {
return code >= 200 && code < 300;
}
clean(data) {
Object.keys(data).forEach(key => data[key] === undefined && delete data[key]);
return data;
}
cleanRequest(request) {
request.headers = this.clean(request.headers);
request.queryParameters = this.clean(request.queryParameters);
return request;
}
}