UNPKG

@eleva-io/erp-sdk

Version:

SDK oficial para el ERP de Eleva

212 lines 8.15 kB
import { lookup as lookupMimeType } from 'mrmime'; import { RemoteElevaError } from '../errors'; import { generateSignature } from './signature'; import { createBuffer, createFile, createFormData, isCrossPlatformBuffer, } from './compatibility'; import pkg from '../../package.json'; export const ELEVA_HEADER_IMPERSONATE = 'x-eleva-impersonate'; export const ELEVA_HEADER_SDK_VERSION = 'x-eleva-sdk-version'; export const ELEVA_HEADER_APP = 'x-eleva-app'; export const ELEVA_HEADER_APP_VERSION = 'x-eleva-app-version'; export class HTTPClient { _config; _logger; constructor(_config, _logger) { this._config = _config; this._logger = _logger; } _buildHeaders(body, extra) { const headers = new Headers({ 'Content-Type': 'application/json' }); headers.set(ELEVA_HEADER_SDK_VERSION, `v${pkg.version}`); headers.set(ELEVA_HEADER_APP, this._config.app); headers.set(ELEVA_HEADER_APP_VERSION, this._config.appVersion); if ('token' in this._config) { headers.set('Authorization', `Bearer ${this._config.token}`); } else { const signBody = body instanceof FormData ? {} : (body ?? {}); const sig = generateSignature(signBody, this._config.apiKey, this._config.apiSecret); headers.set('x-api-key', this._config.apiKey); headers.set('x-timestamp', sig.timestamp.toString()); headers.set('x-signature', sig.signature); if (this._config.emitWebhook) { headers.set('x-eleva-emit-webhook', 'true'); } } if (extra) { for (const [key, value] of Object.entries(extra)) { if (value === null || value === undefined) continue; headers.set(key, Array.isArray(value) ? value.join(', ') : String(value)); } } return headers; } _buildUrl(path, params) { const base = `${this._config.baseURL}${path}`; if (!params) return base; const qs = _buildQueryString(params); return qs ? `${base}?${qs}` : base; } async _request(method, path, body, params, extraHeaders) { const url = this._buildUrl(path, params); const headers = this._buildHeaders(body, extraHeaders); let fetchBody; if (body instanceof FormData) { headers.delete('Content-Type'); fetchBody = body; } else if (body !== undefined) { fetchBody = JSON.stringify(body); } this._logger.debug(`HTTP REQUEST: [${method}] ${path}`); let response; try { response = await fetch(url, { method, headers, body: fetchBody }); } catch (networkError) { throw RemoteElevaError.from(null, { operation: method.toLowerCase(), metadata: _headersToObject(headers), resource: path, payload: body }, {}, networkError); } if (!response.ok) { const responseBody = await response.json().catch(() => null); throw RemoteElevaError.from(responseBody, { operation: method.toLowerCase(), metadata: _headersToObject(headers), resource: path, payload: body }, { statusCode: response.status, metadata: _headersToObject(response.headers), payload: responseBody, }); } const contentType = response.headers.get('content-type'); if (contentType?.includes('application/json')) { return response.json(); } return response.text(); } async get(path, params, headers) { return this._request('GET', path, undefined, params, headers); } async post(path, data, params, headers) { return this._request('POST', path, data, params, headers); } async put(path, data, params, headers) { return this._request('PUT', path, data, params, headers); } async patch(path, data, params, headers) { return this._request('PATCH', path, data, params, headers); } async delete(path, params, headers) { return this._request('DELETE', path, undefined, params, headers); } async getBinary(path, params, headers) { const url = this._buildUrl(path, params); const reqHeaders = this._buildHeaders(undefined, headers); reqHeaders.delete('Content-Type'); this._logger.debug(`HTTP REQUEST: [GET] ${path}`); let response; try { response = await fetch(url, { method: 'GET', headers: reqHeaders }); } catch (networkError) { throw RemoteElevaError.from(null, { operation: 'get', metadata: _headersToObject(reqHeaders), resource: path }, {}, networkError); } if (!response.ok) { const responseBody = await response.json().catch(() => null); throw RemoteElevaError.from(responseBody, { operation: 'get', metadata: _headersToObject(reqHeaders), resource: path }, { statusCode: response.status, metadata: _headersToObject(response.headers), payload: responseBody, }); } return { data: createBuffer(await response.arrayBuffer()), headers: _headersToObject(response.headers), }; } async form(path, data, method = 'POST', params, headers) { return this._request(method, path, _createFormData(data), params, headers); } } function _headersToObject(headers) { const obj = {}; headers.forEach((value, key) => { obj[key] = value; }); return obj; } function _createFormData(data) { const fd = createFormData(); const set = (key, value) => { if (_isFormFileData(value)) { const mimeType = lookupMimeType(value.name); const file = createFile(value.data, value.name, mimeType); fd.append(key, file, value.name); } else if (value !== undefined) { fd.append(key, value === null ? 'null' : value.toString()); } }; Object.entries(data).forEach(([key, value]) => { if (Array.isArray(value)) { const isFileArray = value.length > 0 && value.every(_isFormFileData); if (isFileArray) { value.forEach((fileData) => set(key, fileData)); } else { value.forEach((sv, i) => set(`${key}[${i}]`, sv)); } } else if (_isFormFileData(value)) { set(key, value); } else if (typeof value === 'object' && value !== null) { Object.entries(value).forEach(([sk, sv]) => { set(`${key}[${sk}]`, sv); }); } else { set(key, value); } }); return fd; } function _deepBuildQuery(acc, obj, prefix) { Object.entries(obj).forEach(([key, val]) => { if (val === undefined) return; const newPrefix = prefix ? `${prefix}[${key}]` : key; if (Array.isArray(val)) { val.forEach((v, i) => { acc[`${newPrefix}[${i}]`] = v.toString(); }); } else if (typeof val === 'object' && val !== null) { _deepBuildQuery(acc, val, newPrefix); } else { acc[newPrefix] = val.toString(); } }); } function _buildQueryString(query) { const reqQuery = {}; Object.entries(query).forEach(([key, value]) => { if (value === undefined) return; if (typeof value === 'object' && value !== null) { _deepBuildQuery(reqQuery, value, key); } else { reqQuery[key] = value.toString(); } }); return new URLSearchParams(reqQuery).toString(); } function _isFormFileData(value) { if (typeof value !== 'object' || value === null) { return false; } return ('name' in value && typeof value.name === 'string' && 'data' in value && (typeof value.data === 'string' || isCrossPlatformBuffer(value.data))); } //# sourceMappingURL=http.js.map