import axios, { AxiosInstance, AxiosError } from 'axios'; import { CloverConfig, PaginatedResponse } from '../types/index.js'; export class CloverClient { private client: AxiosInstance; private merchantId: string; constructor(config: CloverConfig) { this.merchantId = config.merchantId; const baseURL = config.environment === 'production' ? 'https://api.clover.com' : 'https://sandbox.dev.clover.com'; this.client = axios.create({ baseURL, headers: { 'Content-Type': 'application/json', ...(config.accessToken && { 'Authorization': `Bearer ${config.accessToken}` }), }, params: { ...(config.apiKey && { access_token: config.apiKey }), }, }); // Response interceptor for error handling this.client.interceptors.response.use( (response) => response, (error: AxiosError) => { if (error.response) { throw new Error(`Clover API Error: ${error.response.status} - ${JSON.stringify(error.response.data)}`); } else if (error.request) { throw new Error('Clover API Error: No response received'); } else { throw new Error(`Clover API Error: ${error.message}`); } } ); } // Generic GET method with pagination support async get(endpoint: string, params: Record = {}): Promise { const url = `/v3/merchants/${this.merchantId}${endpoint}`; const response = await this.client.get(url, { params }); return response.data; } // Generic POST method async post(endpoint: string, data: any): Promise { const url = `/v3/merchants/${this.merchantId}${endpoint}`; const response = await this.client.post(url, data); return response.data; } // Generic PUT method async put(endpoint: string, data: any): Promise { const url = `/v3/merchants/${this.merchantId}${endpoint}`; const response = await this.client.put(url, data); return response.data; } // Generic DELETE method async delete(endpoint: string): Promise { const url = `/v3/merchants/${this.merchantId}${endpoint}`; const response = await this.client.delete(url); return response.data; } // Paginated fetch helper async fetchPaginated( endpoint: string, params: Record = {}, limit?: number ): Promise { const allItems: T[] = []; let offset = 0; const pageSize = 100; while (true) { const response = await this.get>(endpoint, { ...params, limit: pageSize, offset, }); allItems.push(...response.elements); if (response.elements.length < pageSize || (limit && allItems.length >= limit)) { break; } offset += pageSize; if (limit && allItems.length >= limit) { return allItems.slice(0, limit); } } return allItems; } getMerchantId(): string { return this.merchantId; } }