redai-automation-web-sdk
Version:
TypeScript SDK for RedAI Automation Web API - Zalo Personal automation, messaging, advanced sticker search, and bulk operations. 100% compatible with automation-web backend. v1.8.0: Added SessionProxyService for managing proxy assignments to sessions with
332 lines • 9.98 kB
JavaScript
;
/**
* HTTP utility functions for making API requests
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpUtils = exports.HttpClient = exports.HttpError = void 0;
const axios_1 = __importDefault(require("axios"));
/**
* Custom error class for HTTP requests
*/
class HttpError extends Error {
constructor(message, status, code, response) {
super(message);
this.status = status;
this.code = code;
this.response = response;
this.name = 'HttpError';
}
}
exports.HttpError = HttpError;
/**
* HTTP client class for making requests to automation-web API
*/
class HttpClient {
constructor(config) {
this.config = config;
this.axiosInstance = this.createAxiosInstance();
}
/**
* Create axios instance with default configuration
*/
createAxiosInstance() {
const instance = axios_1.default.create({
baseURL: this.config.baseUrl,
timeout: this.config.timeout || 30000,
headers: {
'Content-Type': 'application/json',
'User-Agent': this.config.userAgent || '@redai/automation-web-sdk/1.0.0',
...(this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }),
},
});
// Request interceptor
instance.interceptors.request.use((config) => {
if (this.config.logging) {
console.log(`[HTTP] ${config.method?.toUpperCase()} ${config.url}`, {
params: config.params,
data: config.data,
});
}
return config;
}, (error) => {
if (this.config.logging) {
console.error('[HTTP] Request error:', error);
}
return Promise.reject(error);
});
// Response interceptor
instance.interceptors.response.use((response) => {
if (this.config.logging) {
console.log(`[HTTP] ${response.status} ${response.config.url}`, {
data: response.data,
});
}
return response;
}, (error) => {
if (this.config.logging) {
console.error('[HTTP] Response error:', error.response?.data || error.message);
}
return Promise.reject(this.handleError(error));
});
return instance;
}
/**
* Handle axios errors and convert to HttpError
*/
handleError(error) {
if (error.response) {
// Server responded with error status
const response = error.response.data;
return new HttpError(response.error || response.message || 'Request failed', error.response.status, response.code?.toString(), response);
}
else if (error.request) {
// Request was made but no response received
return new HttpError('Network error - no response received', 0, 'NETWORK_ERROR');
}
else {
// Something else happened
return new HttpError(error.message || 'Unknown error occurred', 0, 'UNKNOWN_ERROR');
}
}
/**
* Make HTTP request with retry logic
*/
async makeRequestWithRetry(requestConfig, retryCount = 0) {
try {
return await this.axiosInstance.request(requestConfig);
}
catch (error) {
const maxRetries = this.config.retryCount || 3;
const retryDelay = this.config.retryDelay || 1000;
if (retryCount < maxRetries && this.shouldRetry(error)) {
if (this.config.logging) {
console.log(`[HTTP] Retrying request (${retryCount + 1}/${maxRetries}) after ${retryDelay}ms`);
}
await this.delay(retryDelay * Math.pow(2, retryCount)); // Exponential backoff
return this.makeRequestWithRetry(requestConfig, retryCount + 1);
}
throw error;
}
}
/**
* Determine if request should be retried
*/
shouldRetry(error) {
// Retry on network errors or 5xx server errors
return (error.code === 'NETWORK_ERROR' ||
(error.status !== undefined && error.status >= 500) ||
error.status === 429 // Rate limit
);
}
/**
* Delay utility for retry logic
*/
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Generic request method
*/
async request(options) {
const requestConfig = {
method: options.method,
url: options.url,
data: options.data,
params: options.params,
headers: options.headers,
timeout: options.timeout || this.config.timeout,
};
const response = await this.makeRequestWithRetry(requestConfig);
// Handle automation-web response format
const responseData = response.data;
// Check for error in response
if (responseData.error) {
throw new HttpError(responseData.error, responseData.code || response.status, responseData.code?.toString(), responseData);
}
// Return the whole AutomationWebResponse structure
// Let the service methods handle extracting result if needed
return responseData;
}
/**
* GET request
*/
async get(url, params, headers) {
return this.request({
method: 'GET',
url,
params,
headers,
});
}
/**
* POST request
*/
async post(url, data, headers) {
return this.request({
method: 'POST',
url,
data,
headers,
});
}
/**
* PUT request
*/
async put(url, data, headers) {
return this.request({
method: 'PUT',
url,
data,
headers,
});
}
/**
* DELETE request
*/
async delete(url, params, headers) {
return this.request({
method: 'DELETE',
url,
params,
headers,
});
}
/**
* PATCH request
*/
async patch(url, data, headers) {
return this.request({
method: 'PATCH',
url,
data,
headers,
});
}
/**
* Update configuration
*/
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
this.axiosInstance = this.createAxiosInstance();
}
/**
* Get current configuration
*/
getConfig() {
return { ...this.config };
}
}
exports.HttpClient = HttpClient;
/**
* Utility functions for HTTP operations
*/
class HttpUtils {
/**
* Build query string from parameters
*/
static buildQueryString(params) {
const searchParams = new URLSearchParams();
Object.entries(params).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
if (Array.isArray(value)) {
value.forEach(item => searchParams.append(key, String(item)));
}
else {
searchParams.append(key, String(value));
}
}
});
return searchParams.toString();
}
/**
* Parse response headers
*/
static parseHeaders(headers) {
const parsed = {};
Object.entries(headers).forEach(([key, value]) => {
parsed[key.toLowerCase()] = value;
});
return parsed;
}
/**
* Check if URL is absolute
*/
static isAbsoluteUrl(url) {
return /^https?:\/\//.test(url);
}
/**
* Join URL paths
*/
static joinPaths(...paths) {
return paths
.map(path => path.replace(/^\/+|\/+$/g, ''))
.filter(path => path.length > 0)
.join('/');
}
/**
* Validate URL format
*/
static isValidUrl(url) {
try {
new URL(url);
return true;
}
catch {
return false;
}
}
/**
* Extract domain from URL
*/
static extractDomain(url) {
try {
const urlObj = new URL(url);
return urlObj.hostname;
}
catch {
return null;
}
}
/**
* Format file size in human readable format
*/
static formatFileSize(bytes) {
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0)
return '0 Bytes';
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + ' ' + sizes[i];
}
/**
* Get MIME type from file extension
*/
static getMimeType(filename) {
const ext = filename.split('.').pop()?.toLowerCase();
const mimeTypes = {
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
png: 'image/png',
gif: 'image/gif',
webp: 'image/webp',
mp4: 'video/mp4',
avi: 'video/avi',
mov: 'video/quicktime',
mp3: 'audio/mpeg',
wav: 'audio/wav',
pdf: 'application/pdf',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
txt: 'text/plain',
json: 'application/json',
xml: 'application/xml',
zip: 'application/zip',
rar: 'application/x-rar-compressed',
};
return mimeTypes[ext || ''] || 'application/octet-stream';
}
}
exports.HttpUtils = HttpUtils;
//# sourceMappingURL=http.utils.js.map