/**
* HTTP client wrapper for Gandi API v5
*/
export interface GandiCredentials {
apiToken: string;
}
export class GandiClient {
private baseURL = 'https://api.gandi.net/v5';
private apiToken: string;
constructor(credentials: GandiCredentials) {
this.apiToken = credentials.apiToken;
}
private getHeaders(): Record<string, string> {
return {
'Authorization': `Bearer ${this.apiToken}`,
'Content-Type': 'application/json',
};
}
/**
* GET request to Gandi API
*/
async get<T = any>(endpoint: string, params?: Record<string, any>): Promise<T> {
let url = `${this.baseURL}${endpoint}`;
if (params) {
const searchParams = new URLSearchParams();
Object.keys(params).forEach(key => {
if (params[key] !== undefined && params[key] !== null) {
searchParams.append(key, String(params[key]));
}
});
const queryString = searchParams.toString();
if (queryString) {
url += `?${queryString}`;
}
}
const response = await fetch(url, {
method: 'GET',
headers: this.getHeaders(),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Gandi API Error (${response.status}): ${errorData.message || response.statusText}`);
}
return await response.json();
}
/**
* POST request to Gandi API
*/
async post<T = any>(endpoint: string, data?: any): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
method: 'POST',
headers: this.getHeaders(),
body: data ? JSON.stringify(data) : undefined,
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Gandi API Error (${response.status}): ${errorData.message || response.statusText}`);
}
return await response.json();
}
/**
* PUT request to Gandi API
*/
async put<T = any>(endpoint: string, data?: any): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
method: 'PUT',
headers: this.getHeaders(),
body: data ? JSON.stringify(data) : undefined,
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Gandi API Error (${response.status}): ${errorData.message || response.statusText}`);
}
return await response.json();
}
/**
* DELETE request to Gandi API
*/
async delete<T = any>(endpoint: string): Promise<T> {
const url = `${this.baseURL}${endpoint}`;
const response = await fetch(url, {
method: 'DELETE',
headers: this.getHeaders(),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(`Gandi API Error (${response.status}): ${errorData.message || response.statusText}`);
}
// Handle empty response for DELETE requests
const text = await response.text();
return text ? JSON.parse(text) : null;
}
}
/**
* Get Gandi credentials from environment variables
*/
export function getGandiCredentials(): GandiCredentials {
const apiToken = process.env.GANDI_API_TOKEN;
if (!apiToken) {
throw new Error(
"Gandi API token is required. Set the GANDI_API_TOKEN environment variable."
);
}
return { apiToken };
}