UNPKG

@smash-sdk/core

Version:

Smash Sdk Core

151 lines (150 loc) 5.75 kB
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; } }