- API client with Clover REST API v3 integration (OAuth2 + API key auth) - 50+ comprehensive tools across 10 categories: * Orders: list, get, create, update, delete, add/remove line items, discounts, payments, fire order * Inventory: items, categories, modifiers, stock management * Customers: CRUD, search, addresses, payment cards * Employees: CRUD, roles, shifts, clock in/out * Payments: list, get, refunds * Merchants: settings, devices, tender types * Discounts: CRUD operations * Taxes: CRUD, tax rates * Reports: sales summary, revenue by item/category, employee performance * Cash: cash drawer tracking and events - 18 React MCP apps with full UI: * Order management: dashboard, detail, grid * Inventory: dashboard, detail, category manager * Customer: detail, grid * Employee: dashboard, schedule * Payment history * Analytics: sales dashboard, revenue by item, revenue by category * Configuration: discount manager, tax manager, device manager * Cash drawer - Complete TypeScript types for Clover API - Pagination support with automatic result fetching - Comprehensive error handling - Full README with examples and setup guide
106 lines
2.9 KiB
TypeScript
106 lines
2.9 KiB
TypeScript
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<T>(endpoint: string, params: Record<string, any> = {}): Promise<T> {
|
|
const url = `/v3/merchants/${this.merchantId}${endpoint}`;
|
|
const response = await this.client.get<T>(url, { params });
|
|
return response.data;
|
|
}
|
|
|
|
// Generic POST method
|
|
async post<T>(endpoint: string, data: any): Promise<T> {
|
|
const url = `/v3/merchants/${this.merchantId}${endpoint}`;
|
|
const response = await this.client.post<T>(url, data);
|
|
return response.data;
|
|
}
|
|
|
|
// Generic PUT method
|
|
async put<T>(endpoint: string, data: any): Promise<T> {
|
|
const url = `/v3/merchants/${this.merchantId}${endpoint}`;
|
|
const response = await this.client.put<T>(url, data);
|
|
return response.data;
|
|
}
|
|
|
|
// Generic DELETE method
|
|
async delete<T>(endpoint: string): Promise<T> {
|
|
const url = `/v3/merchants/${this.merchantId}${endpoint}`;
|
|
const response = await this.client.delete<T>(url);
|
|
return response.data;
|
|
}
|
|
|
|
// Paginated fetch helper
|
|
async fetchPaginated<T>(
|
|
endpoint: string,
|
|
params: Record<string, any> = {},
|
|
limit?: number
|
|
): Promise<T[]> {
|
|
const allItems: T[] = [];
|
|
let offset = 0;
|
|
const pageSize = 100;
|
|
|
|
while (true) {
|
|
const response = await this.get<PaginatedResponse<T>>(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;
|
|
}
|
|
}
|