/** * Hetzner Cloud API client for VPS provisioning. */ const HETZNER_API = "https://api.hetzner.cloud/v1"; function headers(): Record { const token = process.env.HETZNER_API_TOKEN; if (!token) throw new Error("HETZNER_API_TOKEN not set"); return { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }; } export interface HetznerServer { id: number; name: string; status: string; public_net: { ipv4: { ip: string }; ipv6: { ip: string }; }; server_type: { name: string }; datacenter: { name: string }; } export async function createServer(opts: { name: string; serverType: string; region: string; userData: string; }): Promise<{ serverId: string; ip: string }> { const res = await fetch(`${HETZNER_API}/servers`, { method: "POST", headers: headers(), body: JSON.stringify({ name: opts.name, server_type: opts.serverType, location: opts.region, image: "ubuntu-22.04", user_data: opts.userData, start_after_create: true, }), }); if (!res.ok) { const err = await res.text(); throw new Error(`Hetzner create failed: ${res.status} ${err}`); } const data = await res.json(); return { serverId: String(data.server.id), ip: data.server.public_net.ipv4.ip, }; } export async function getServer(serverId: string): Promise { const res = await fetch(`${HETZNER_API}/servers/${serverId}`, { headers: headers() }); if (!res.ok) return null; const data = await res.json(); return data.server; } export async function deleteServer(serverId: string): Promise { const res = await fetch(`${HETZNER_API}/servers/${serverId}`, { method: "DELETE", headers: headers(), }); return res.ok; } export async function serverAction(serverId: string, action: "poweron" | "poweroff" | "reboot"): Promise { const res = await fetch(`${HETZNER_API}/servers/${serverId}/actions/${action}`, { method: "POST", headers: headers(), }); return res.ok; }