81 lines
1.9 KiB
TypeScript
81 lines
1.9 KiB
TypeScript
/**
|
|
* Hetzner Cloud API client for VPS provisioning.
|
|
*/
|
|
|
|
const HETZNER_API = "https://api.hetzner.cloud/v1";
|
|
|
|
function headers(): Record<string, string> {
|
|
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<HetznerServer | null> {
|
|
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<boolean> {
|
|
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<boolean> {
|
|
const res = await fetch(`${HETZNER_API}/servers/${serverId}/actions/${action}`, {
|
|
method: "POST",
|
|
headers: headers(),
|
|
});
|
|
return res.ok;
|
|
}
|