@eleva-io/erp-sdk
Version:
SDK oficial para el ERP de Eleva
212 lines • 8.15 kB
JavaScript
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