/**
* FitSlot API Service
* Handles communication with the FitSlot API
*/
import axios, { AxiosInstance, AxiosError } from 'axios';
import {
Ticket,
CreateTicketRequest,
UpdateTicketRequest,
FitSlotConfig,
TicketStatus
} from '../types/index.js';
import { logger } from '../utils/logger.js';
export class FitSlotAPIService {
private client: AxiosInstance;
private config: FitSlotConfig;
constructor(config: FitSlotConfig) {
this.config = config;
this.client = axios.create({
baseURL: config.apiUrl,
timeout: config.timeout || 30000,
headers: {
'Content-Type': 'application/json',
...(config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` })
}
});
// Add request interceptor for logging
this.client.interceptors.request.use(
(config) => {
logger.debug('API Request', {
method: config.method,
url: config.url,
data: config.data
});
return config;
},
(error) => {
logger.error('API Request Error', error);
return Promise.reject(error);
}
);
// Add response interceptor for logging and error handling
this.client.interceptors.response.use(
(response) => {
logger.debug('API Response', {
status: response.status,
data: response.data
});
return response;
},
(error: AxiosError) => {
logger.error('API Response Error', {
status: error.response?.status,
data: error.response?.data,
message: error.message
});
return Promise.reject(this.formatError(error));
}
);
}
private formatError(error: AxiosError): Error {
if (error.response) {
return new Error(
`API Error: ${error.response.status} - ${JSON.stringify(error.response.data)}`
);
} else if (error.request) {
return new Error('API Error: No response received from server');
} else {
return new Error(`API Error: ${error.message}`);
}
}
/**
* Create a new support ticket
*/
async createTicket(request: CreateTicketRequest): Promise<Ticket> {
try {
const response = await this.client.post<Ticket>('/api/tickets', request);
logger.info('Ticket created successfully', { ticketId: response.data.id });
return response.data;
} catch (error) {
logger.error('Failed to create ticket', error);
throw error;
}
}
/**
* Get all tickets for a user
*/
async getTickets(userId: string, status?: TicketStatus): Promise<Ticket[]> {
try {
const params: any = { userId };
if (status) {
params.status = status;
}
const response = await this.client.get<Ticket[]>('/api/tickets', { params });
logger.info('Tickets retrieved', { count: response.data.length });
return response.data;
} catch (error) {
logger.error('Failed to get tickets', error);
throw error;
}
}
/**
* Get a specific ticket by ID
*/
async getTicket(ticketId: string): Promise<Ticket> {
try {
const response = await this.client.get<Ticket>(`/api/tickets/${ticketId}`);
logger.info('Ticket retrieved', { ticketId });
return response.data;
} catch (error) {
logger.error('Failed to get ticket', error);
throw error;
}
}
/**
* Update an existing ticket
*/
async updateTicket(request: UpdateTicketRequest): Promise<Ticket> {
try {
const { id, ...updateData } = request;
const response = await this.client.patch<Ticket>(
`/api/tickets/${id}`,
updateData
);
logger.info('Ticket updated successfully', { ticketId: id });
return response.data;
} catch (error) {
logger.error('Failed to update ticket', error);
throw error;
}
}
/**
* Delete a ticket
*/
async deleteTicket(ticketId: string): Promise<void> {
try {
await this.client.delete(`/api/tickets/${ticketId}`);
logger.info('Ticket deleted successfully', { ticketId });
} catch (error) {
logger.error('Failed to delete ticket', error);
throw error;
}
}
}