import axios, { AxiosRequestConfig } from "axios";
export async function makePlaneRequest<T>(method: string, path: string, body: any = null): Promise<T> {
// Ensure /api/v1 is included in the base URL
let hostUrl = process.env.PLANE_API_HOST_URL || "https://api.plane.so";
if (!hostUrl.endsWith("/")) hostUrl += "/";
if (!hostUrl.includes("/api/v1")) {
hostUrl = hostUrl.replace(/\/$/, "") + "/api/v1/";
}
// Remove any double slashes except after https://
hostUrl = hostUrl.replace(/([^:]\/)\/+/, "$1");
const url = `${hostUrl}${path}`;
const headers: Record<string, string> = {
"X-API-Key": process.env.PLANE_API_KEY || "",
Accept: "application/json",
};
// Only add Content-Type for non-GET requests
if (method.toUpperCase() !== "GET") {
headers["Content-Type"] = "application/json";
}
// Debug log
console.log("[DEBUG] Plane API Request", {
method,
url,
headers,
body,
});
try {
const config: AxiosRequestConfig = {
url,
method,
headers,
};
// Only include body for non-GET requests
if (method.toUpperCase() !== "GET" && body !== null) {
config.data = body;
}
const response = await axios(config);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
// Log error response for debugging
if (error.response) {
console.error("[DEBUG] Plane API Error Response", {
status: error.response.status,
data: error.response.data,
});
}
throw new Error(`Request failed: ${error.message}`);
}
throw error;
}
}