UNPKG

trade360-nodejs-sdk

Version:
200 lines 9.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseHttpClient = void 0; const axios_1 = require("axios"); const lodash_1 = require("lodash"); const common_1 = require("../common"); const http_response_dto_1 = require("../common/dtos/http-response.dto"); const errors_1 = require("../../entities/errors"); const services_1 = require("./services"); const validators_1 = require("./validators"); const _logger_1 = require("../../logger"); const _utilities_1 = require("../../utilities"); /** * BaseHttpClient class is responsible for sending requests * to the REST API. It is a base class for all HTTP clients. * It contains the basic logic for sending requests. * @param apiBaseUrl The base URL of the REST API * @param packageCredentials The package credentials for the API * @param logger The logger instance to be used for logging */ class BaseHttpClient { constructor({ restApiBaseUrl, packageCredentials, logger }) { this.requestSettings = validators_1.RequestSettingsValidator.validate({ restApiBaseUrl, ...packageCredentials, }); this.logger = !(0, lodash_1.isNil)(logger) ? logger : new _logger_1.ConsoleAdapter(); this.baseUrl = encodeURI(restApiBaseUrl); this.httpService = new services_1.AxiosService(this.baseUrl); } /** * This method is responsible for sending POST requests to * the customers API. basic POST request, with body contains * packageId, userName and password. * The request expect getting generic type R which declare * the expected response structure. * @param route string that represent the route expected to * be sent to the API endpoint. * @param responseBodyType new instance of the expected response * structure. * @param requestBody optional parameter that represent the body * of the request. * @returns promise with the TResponse type response type of * the API. */ async postRequest({ route, responseBodyType, requestBody, }) { this.requestSettings = !(0, lodash_1.isNil)(requestBody) ? requestBody : _utilities_1.TransformerUtil.transform(this.requestSettings, common_1.HttpRequestDto); const responsePayloadDto = http_response_dto_1.HttpResponsePayloadDto.createPayloadDto(responseBodyType); try { const response = await this.httpService.post(route, this.requestSettings); return await this.handleValidResponse(response, responsePayloadDto); } catch (error) { this.handleErrorResponse(error, responsePayloadDto); } } /** * This method is responsible for sending GET requests to the * customers API. The request expect getting generic type R which * declare the expected response structure. * @param route string that represent the route expected to be * sent to the API endpoint. * @param responseBodyType new instance of the expected response * structure. * @param params optional parameter that represent the query * parameters of the request. * @returns promise with the TResponse type response type of the * API. */ async getRequest({ route, responseBodyType, requestBody: params, }) { this.requestSettings = !(0, lodash_1.isNil)(params) ? params : _utilities_1.TransformerUtil.transform(this.requestSettings, common_1.HttpRequestDto); const responsePayloadDto = http_response_dto_1.HttpResponsePayloadDto.createPayloadDto(responseBodyType); try { // Build the query string from the request object properties const queryString = this.buildQueryString(params); const fullUri = `${route}?${queryString}`; const httpResponse = await this.httpService.get(fullUri); return await this.handleValidResponse(httpResponse, responsePayloadDto); } catch (error) { this.handleErrorResponse(error, responsePayloadDto); } } /** * This method is responsible for handling the valid response. * @param httpResponse The response received from the API call * @param responsePayloadDto The response payload DTO to be used * for transforming the response * @returns The response payload DTO with the required properties * serialized to PascalCase format (API format) * @throws HttpResponseError if the response does not contain the * required properties */ async handleValidResponse(httpResponse, responsePayloadDto) { const { data } = httpResponse; const responsePayload = _utilities_1.TransformerUtil.transform(data, responsePayloadDto); this.validateResponsePayloadStructure(responsePayload); // Serialize the response body back to PascalCase format (API format) const serializedBody = _utilities_1.TransformerUtil.serializeToApiFormat(responsePayload.body); // Return the serialized object as TResponse (maintains type compatibility) return serializedBody; } /** * This method is responsible for validating the structure of the * response payload. It checks if the response payload contains the * required properties. * @param responsePayload The response payload to be validated * @returns void if the response payload contains the required * properties * @throws HttpResponseError if the response payload does not contain * the required properties */ validateResponsePayloadStructure(responsePayload) { const { header, body } = responsePayload; if ((0, lodash_1.isNil)(header)) { throw new errors_1.HttpResponseError("'Header' property is missing. Please ensure that you use the correct URL."); } if ((0, lodash_1.isNil)(body)) { throw new errors_1.HttpResponseError("'Body' property is missing. Please ensure that you use the correct URL."); } } /** * This method is responsible for handling the error response. * It throws an error with the appropriate message based on the error * response received. If the error response is not an AxiosError, it * throws the error as is. * @param errorResponse The error response received from the API call * @param responsePayloadDto The response payload DTO to be used for * transforming the error response * @returns void if the error response is handled successfully * @throws HttpResponseError if the error response contains errors in * the response body, it throws an error with the error messages as * the context of the error response * @throws HttpResponseError if the error response is not an AxiosError * or if the error response is an AxiosError with a status code that is * not handled by the HttpResponseError class */ handleErrorResponse(errorResponse, responsePayloadDto) { if ((0, lodash_1.isNil)(errorResponse)) { throw new errors_1.HttpResponseError('', { context: 'No response received' }); } else if (!(errorResponse instanceof axios_1.AxiosError)) throw errorResponse; const { response, message, cause } = errorResponse; const rawErrorResponse = errorResponse.toString(); if ((0, lodash_1.isNil)(response)) { throw new errors_1.HttpResponseError(`with message: ${message}`, { context: rawErrorResponse, cause, }); } const { data, statusText } = response; if ((0, lodash_1.isNil)(data)) { throw errors_1.HttpResponseError.getHttpResponseErrorByStatusCode(undefined, rawErrorResponse, statusText, message); } const transformed = _utilities_1.TransformerUtil.transform(data, responsePayloadDto); if (!transformed.header) { throw new errors_1.HttpResponseError("Missing 'header' in error response", { context: data }); } const { httpStatusCode, errors } = transformed.header; if (!(0, lodash_1.isNil)(errors)) { const errorsArray = (0, lodash_1.map)(errors, (error) => error.message); throw new errors_1.HttpResponseError('', { context: errorsArray, cause: errorResponse, }); } throw errors_1.HttpResponseError.getHttpResponseErrorByStatusCode(httpStatusCode, rawErrorResponse, statusText, message); } /** * This method is responsible for building the query string from the * request parameters. * @param requestParams The request parameters to be used for building * the query string * @returns The query string built from the request parameters or an * */ buildQueryString(requestParams) { if ((0, lodash_1.isNil)(requestParams)) return ''; const queryParams = []; (0, lodash_1.forEach)(requestParams, (value, key) => { if ((0, lodash_1.isArray)(value)) { (0, lodash_1.forEach)(value, (element) => { queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(element))}`); }); } else if (!(0, lodash_1.isNil)(value)) { queryParams.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); } }); return queryParams.join('&'); } } exports.BaseHttpClient = BaseHttpClient; //# sourceMappingURL=base-http-client.js.map