UNPKG

admitad-api-client

Version:

A TypeScript/JavaScript client for the Admitad API with built-in authentication and token management

193 lines 7.23 kB
import { encodeCredentials, createAuthHeader, isTokenExpired, calculateExpirationTime } from '../utils/auth.js'; export class AdmitadApiClient { constructor(config) { this.accessToken = null; this.refreshToken = null; this.tokenExpiresAt = null; this.config = { baseUrl: 'https://api.admitad.com', ...config }; // Use provided base64Auth or generate it from clientId and clientSecret this.base64Auth = config.base64Auth || encodeCredentials(config.clientId, config.clientSecret); } /** * Authenticates with Admitad API and obtains access token * @param scopes - Array of scopes to request access for * @returns Promise resolving to token response */ async authenticate(scopes) { const url = `${this.config.baseUrl}/token/`; const scope = scopes.join(' '); const requestData = { client_id: this.config.clientId, scope, grant_type: 'client_credentials' }; const body = new URLSearchParams(requestData).toString(); const response = await fetch(url, { method: 'POST', headers: { 'Authorization': createAuthHeader(this.base64Auth), 'Content-Type': 'application/x-www-form-urlencoded' }, body }); if (!response.ok) { const errorData = await response.json(); throw new Error(`Authentication failed: ${errorData.error} - ${errorData.error_description || 'Unknown error'}`); } const tokenData = await response.json(); // Store token data this.accessToken = tokenData.access_token; this.refreshToken = tokenData.refresh_token; this.tokenExpiresAt = calculateExpirationTime(tokenData.expires_in); return tokenData; } /** * Ensures we have a valid access token, refreshing if necessary */ async ensureValidToken() { if (!this.accessToken || !this.tokenExpiresAt || isTokenExpired(this.tokenExpiresAt)) { throw new Error('No valid token available. Please authenticate first.'); } } /** * Makes an authenticated request to the Admitad API * @param endpoint - API endpoint (without base URL) * @param options - Request options * @returns Promise resolving to response data */ async request(endpoint, options = {}) { await this.ensureValidToken(); const url = new URL(endpoint, this.config.baseUrl); // Add query parameters if provided if (options.params) { Object.entries(options.params).forEach(([key, value]) => { url.searchParams.append(key, String(value)); }); } const headers = { 'Authorization': `Bearer ${this.accessToken}`, 'Content-Type': 'application/json', ...options.headers }; const requestOptions = { method: options.method || 'GET', headers }; if (options.body && (options.method === 'POST' || options.method === 'PUT')) { requestOptions.body = JSON.stringify(options.body); } const response = await fetch(url.toString(), requestOptions); if (!response.ok) { let errorMessage = `Request failed with status ${response.status}`; try { const errorData = await response.json(); errorMessage = errorData.error || errorData.message || errorMessage; } catch { // If we can't parse error as JSON, use the status text errorMessage = response.statusText || errorMessage; } throw new Error(errorMessage); } // Handle empty responses const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } return await response.text(); } /** * Gets current access token */ getAccessToken() { return this.accessToken; } /** * Gets current refresh token */ getRefreshToken() { return this.refreshToken; } /** * Checks if current token is valid and not expired */ isAuthenticated() { return !!(this.accessToken && this.tokenExpiresAt && !isTokenExpired(this.tokenExpiresAt)); } /** * Clears stored authentication data */ logout() { this.accessToken = null; this.refreshToken = null; this.tokenExpiresAt = null; } /** * Gets commission rates for AliExpress products * @param urls - Array of product URLs to check commission rates for * @returns Promise resolving to commission rates response */ async getAliExpressCommissionRates(urls) { const requestBody = { urls }; return await this.request('/aliexpress/commission_rates/', { method: 'POST', body: requestBody }); } /** * Shortens an Admitad URL using the URL shortener service * @param link - The Admitad link to shorten (must belong to Admitad's domains) * @returns Promise resolving to shortened URL response */ async shortenUrl(link) { const requestBody = { link }; return await this.request('/shortlink/modify/', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(requestBody).toString() }); } /** * Generates deeplinks for affiliate programs * @param websiteId - The ad space ID (w_id) * @param campaignId - The affiliate program ID (c_id) * @param params - Deeplink generation parameters * @returns Promise resolving to generated deeplinks */ async generateDeeplinks(websiteId, campaignId, params) { const endpoint = `/deeplink/${websiteId}/advcampaign/${campaignId}/`; // Convert ulp to array if it's a string const ulpArray = Array.isArray(params.ulp) ? params.ulp : [params.ulp]; // Build query parameters const queryParams = {}; // Add subid parameters if provided if (params.subid) queryParams.subid = params.subid; if (params.subid1) queryParams.subid1 = params.subid1; if (params.subid2) queryParams.subid2 = params.subid2; if (params.subid3) queryParams.subid3 = params.subid3; if (params.subid4) queryParams.subid4 = params.subid4; // Add multiple ulp parameters const searchParams = new URLSearchParams(); Object.entries(queryParams).forEach(([key, value]) => { searchParams.append(key, value); }); ulpArray.forEach(ulp => { searchParams.append('ulp', ulp); }); return await this.request(endpoint, { method: 'GET', params: Object.fromEntries(searchParams.entries()) }); } } //# sourceMappingURL=admitad-client.js.map