hetzner-ts
Version:
A TypeScript SDK for the Hetzner Cloud API
1 lines • 121 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/base.ts","../src/billing/billing.ts","../src/firewalls/actions.ts","../src/firewalls/firewalls.ts","../src/floating-ips/actions.ts","../src/floating-ips/floating-ips.ts","../src/locations/locations.ts","../src/networks/actions.ts","../src/networks/networks.ts","../src/security/actions.ts","../src/security/certificates.ts","../src/security/security.ts","../src/volumes/actions.ts","../src/volumes/volumes.ts","../src/load-balancers/actions.ts","../src/load-balancers/load-balancers.ts","../src/actions/actions.ts","../src/servers/images/images.ts","../src/servers/primary-ip/primary-ip.ts","../src/servers/placement-groups/placement-group.ts","../src/servers/isos/isos.ts","../src/servers/server-types/server-types.ts","../src/servers/actions/actions.ts","../src/servers/servers.ts"],"sourcesContent":["import { BaseAPI } from \"./base\"\nimport { Billing } from \"./billing/billing\"\nimport { Firewalls } from \"./firewalls/firewalls\"\nimport { FloatingIPs } from \"./floating-ips/floating-ips\"\nimport { Datacenters, Locations } from \"./locations/locations\"\nimport { Networks } from \"./networks/networks\"\nimport { SSHKeys, Certificates } from \"./security/security\"\nimport { Volumes } from \"./volumes/volumes\"\nimport { LoadBalancers } from \"./load-balancers/load-balancers\"\nimport { Actions } from \"./actions/actions\"\nimport { Servers } from \"./servers/servers\"\nexport class HetznerAPI extends BaseAPI {\n get actions() {\n return new Actions(this.token)\n }\n\n get billing() {\n return new Billing(this.token)\n }\n\n get certificates() {\n return new Certificates(this.token)\n }\n\n get datacenters() {\n return new Datacenters(this.token)\n }\n\n get firewalls() {\n return new Firewalls(this.token)\n }\n\n get floatingIps() {\n return new FloatingIPs(this.token)\n }\n\n get loadBalancers() {\n return new LoadBalancers(this.token)\n }\n\n get locations() {\n return new Locations(this.token)\n }\n\n get networks() {\n return new Networks(this.token)\n }\n\n get servers() {\n return new Servers(this.token)\n }\n\n get sshKeys() {\n return new SSHKeys(this.token)\n }\n\n get volumes() {\n return new Volumes(this.token)\n }\n}\n","import type { APIError } from \"./types\"\n\nexport class BaseAPI {\n protected token: string\n protected baseUrl: string\n\n constructor(token: string, baseUrl?: string) {\n this.token = token\n this.baseUrl = baseUrl || \"https://api.hetzner.cloud/v1\"\n }\n\n public async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<{ success: true; response: T } | { success: false; response: APIError }> {\n const res = await fetch(`${this.baseUrl}${endpoint}`, {\n ...options,\n headers: {\n ...(options.headers || {}),\n Authorization: `Bearer ${this.token}`,\n \"Content-Type\": \"application/json\",\n },\n })\n const response = res.status === 204 ? null : await res.json()\n if (!res.ok) {\n return {\n success: false,\n response: response as APIError,\n }\n }\n return {\n success: true,\n response: response as T,\n }\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type { PricingResponse } from \"./types\"\n\n/**\n * Billing API\n *\n * Returns prices for resources.\n * https://docs.hetzner.cloud/#billing\n *\n */\nexport class Billing extends BaseAPI {\n /**\n * Get all prices for resources\n * VAT and currency of the Project owner are used for calculations.\n * Both net and gross prices are included in the response.\n */\n async get(): Promise<\n { success: true; response: PricingResponse } | { success: false; response: APIError }\n > {\n return this.request<PricingResponse>(\"/pricing\")\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type {\n FirewallAction,\n FirewallActionsResponse,\n FirewallRule,\n FirewallResource,\n SortOption,\n ActionStatus,\n} from \"./types\"\n\n/**\n * Firewall Actions API\n *\n * Returns all Actions for Firewalls.\n * https://docs.hetzner.cloud/#firewalls-actions\n *\n */\nexport class FirewallActions extends BaseAPI {\n /**\n * List all actions for firewalls\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(params?: {\n id?: number\n sort?: SortOption\n status?: ActionStatus\n page?: number\n per_page?: number\n }): Promise<\n { success: true; response: FirewallActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<FirewallActionsResponse>(\n `/firewalls/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for a firewall\n */\n async get(\n firewallId: number,\n actionId: number,\n ): Promise<\n { success: true; response: { action: FirewallAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: FirewallAction }>(`/firewalls/${firewallId}/actions/${actionId}`)\n }\n\n /**\n * Apply firewall to resources\n */\n async applyToResources(\n firewallId: number,\n resources: FirewallResource[],\n ): Promise<\n { success: true; response: { action: FirewallAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: FirewallAction }>(\n `/firewalls/${firewallId}/actions/apply_to_resources`,\n {\n method: \"POST\",\n body: JSON.stringify({ apply_to: resources }),\n },\n )\n }\n\n /**\n * Remove firewall from resources\n */\n async removeFromResources(\n firewallId: number,\n resources: FirewallResource[],\n ): Promise<\n { success: true; response: { action: FirewallAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: FirewallAction }>(\n `/firewalls/${firewallId}/actions/remove_from_resources`,\n {\n method: \"POST\",\n body: JSON.stringify({ remove_from: resources }),\n },\n )\n }\n\n /**\n * Set firewall rules\n */\n async setRules(\n firewallId: number,\n rules: FirewallRule[] | [], // Pass an empty array to remove all rules\n ): Promise<\n { success: true; response: { action: FirewallAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: FirewallAction }>(`/firewalls/${firewallId}/actions/set_rules`, {\n method: \"POST\",\n body: JSON.stringify({ rules }),\n })\n }\n\n /**\n * Get all actions for a specific firewall\n */\n async getFirewallActions(\n firewallId: number,\n params?: {\n sort?: SortOption\n status?: ActionStatus\n page?: number\n per_page?: number\n },\n ): Promise<\n { success: true; response: FirewallActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<FirewallActionsResponse>(\n `/firewalls/${firewallId}/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Returns a specific Action for a Firewall.\n */\n async getFirewallAction(\n firewallId: number,\n actionId: number,\n ): Promise<\n { success: true; response: { action: FirewallAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: FirewallAction }>(`/firewalls/${firewallId}/actions/${actionId}`)\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type {\n Firewall,\n FirewallsResponse,\n FirewallRule,\n FirewallResource,\n FirewallCreateResponse,\n} from \"./types\"\nimport { FirewallActions } from \"./actions\"\n\nexport interface ListFirewallsParams {\n name?: string\n label_selector?: string\n sort?:\n | \"id\"\n | \"id:asc\"\n | \"id:desc\"\n | \"name\"\n | \"name:asc\"\n | \"name:desc\"\n | \"created\"\n | \"created:asc\"\n | \"created:desc\"\n page?: number\n per_page?: number\n}\n\nexport interface CreateFirewallParams {\n name: string // max 128 chars\n labels?: Record<string, string>\n rules?: FirewallRule[]\n apply_to?: FirewallResource[]\n}\n\nexport interface UpdateFirewallParams {\n name?: string // max 128 chars\n labels?: Record<string, string>\n}\n\n/**\n * Firewalls API\n *\n * Firewalls can limit the network access to or from your resources.\n * https://docs.hetzner.cloud/#firewalls\n *\n */\nexport class Firewalls extends BaseAPI {\n private _actions: FirewallActions | null = null\n\n /**\n * Get the actions instance for managing firewall actions\n */\n get actions(): FirewallActions {\n if (!this._actions) {\n this._actions = new FirewallActions(this.token)\n }\n return this._actions\n }\n\n /**\n * List all firewalls with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListFirewallsParams,\n ): Promise<\n { success: true; response: FirewallsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<FirewallsResponse>(`/firewalls${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Create a new firewall\n * @param params Parameters for creating the firewall\n */\n async create(\n params: CreateFirewallParams,\n ): Promise<\n { success: true; response: FirewallCreateResponse } | { success: false; response: APIError }\n > {\n return this.request<FirewallCreateResponse>(\"/firewalls\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Get a specific firewall by ID\n * @param id The firewall ID\n */\n async get(\n id: number,\n ): Promise<\n { success: true; response: { firewall: Firewall } } | { success: false; response: APIError }\n > {\n return this.request<{ firewall: Firewall }>(`/firewalls/${id}`)\n }\n\n /**\n * Update a firewall's properties\n * @param id The firewall ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateFirewallParams,\n ): Promise<\n { success: true; response: { firewall: Firewall } } | { success: false; response: APIError }\n > {\n return this.request<{ firewall: Firewall }>(`/firewalls/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a firewall\n * @param id The firewall ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/firewalls/${id}`, {\n method: \"DELETE\",\n })\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type {\n AssignFloatingIPParams,\n ChangeDNSPTRParams,\n ChangeProtectionParams,\n FloatingIPAction,\n FloatingIPActionsResponse,\n ListFloatingIPActionsParams,\n} from \"./types\"\n\nexport class FloatingIPActions extends BaseAPI {\n /**\n * List all actions for Floating IPs\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListFloatingIPActionsParams,\n ): Promise<\n { success: true; response: FloatingIPActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<FloatingIPActionsResponse>(\n `/floating_ips/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for Floating IPs\n * @param actionId The action ID\n */\n async get(\n actionId: number,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(`/floating_ips/actions/${actionId}`)\n }\n\n /**\n * List actions for a specific Floating IP\n * @param floatingIpId The Floating IP ID\n * @param params Optional parameters for filtering and pagination\n */\n async listForFloatingIP(\n floatingIpId: number,\n params?: ListFloatingIPActionsParams, // Assuming similar params as listAll, adjust if different\n ): Promise<\n { success: true; response: FloatingIPActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<FloatingIPActionsResponse>(\n `/floating_ips/${floatingIpId}/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Assign a Floating IP to a Server\n * @param floatingIpId The Floating IP ID\n * @param params Parameters for assigning the Floating IP\n */\n async assign(\n floatingIpId: number,\n params: AssignFloatingIPParams,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(`/floating_ips/${floatingIpId}/actions/assign`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Unassign a Floating IP\n * @param floatingIpId The Floating IP ID\n */\n async unassign(\n floatingIpId: number,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(`/floating_ips/${floatingIpId}/actions/unassign`, {\n method: \"POST\",\n })\n }\n\n /**\n * Change Reverse DNS (PTR) for a Floating IP\n * @param floatingIpId The Floating IP ID\n * @param params Parameters for changing the DNS PTR record\n */\n async changeDNSPTR(\n floatingIpId: number,\n params: ChangeDNSPTRParams,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(`/floating_ips/${floatingIpId}/actions/change_dns_ptr`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Change Floating IP Protection\n * @param floatingIpId The Floating IP ID\n * @param params Parameters for changing the protection status\n */\n async changeProtection(\n floatingIpId: number,\n params: ChangeProtectionParams,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(\n `/floating_ips/${floatingIpId}/actions/change_protection`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n )\n }\n\n /**\n * Get a specific action for a specific Floating IP\n * @param floatingIpId The Floating IP ID\n * @param actionId The action ID\n */\n async getForFloatingIP(\n floatingIpId: number,\n actionId: number,\n ): Promise<\n { success: true; response: FloatingIPAction } | { success: false; response: APIError }\n > {\n return this.request<FloatingIPAction>(`/floating_ips/${floatingIpId}/actions/${actionId}`)\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport { FloatingIPActions } from \"./actions\"\nimport type {\n CreateFloatingIPParams,\n FloatingIP,\n FloatingIPsResponse,\n ListFloatingIPsParams,\n UpdateFloatingIPParams,\n} from \"./types\"\n\nexport class FloatingIPs extends BaseAPI {\n private _actions: FloatingIPActions | null = null\n\n /**\n * List all Floating IPs with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListFloatingIPsParams,\n ): Promise<\n { success: true; response: FloatingIPsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<FloatingIPsResponse>(`/floating_ips${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Get a specific Floating IP by ID\n * @param id The Floating IP ID\n */\n async get(\n id: number,\n ): Promise<{ success: true; response: FloatingIP } | { success: false; response: APIError }> {\n return this.request<FloatingIP>(`/floating_ips/${id}`)\n }\n\n /**\n * Create a new Floating IP\n * @param params Parameters for creating the Floating IP\n */\n async create(\n params: CreateFloatingIPParams,\n ): Promise<\n | { success: true; response: { floating_ip: FloatingIP } }\n | { success: false; response: APIError }\n > {\n return this.request<{ floating_ip: FloatingIP }>(\"/floating_ips\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Update a Floating IP's properties\n * @param id The Floating IP ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateFloatingIPParams,\n ): Promise<\n | { success: true; response: { floating_ip: FloatingIP } }\n | { success: false; response: APIError }\n > {\n return this.request<{ floating_ip: FloatingIP }>(`/floating_ips/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a Floating IP\n * @param id The Floating IP ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/floating_ips/${id}`, {\n method: \"DELETE\",\n })\n }\n\n get actions(): FloatingIPActions {\n if (!this._actions) {\n this._actions = new FloatingIPActions(this.token)\n }\n return this._actions\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type { Datacenter, DatacentersResponse, Location, LocationsResponse } from \"./types\"\n\ntype SortableLocationField = \"id\" | \"id:asc\" | \"id:desc\" | \"name\" | \"name:asc\" | \"name:desc\"\n\nexport interface ListLocationsParams {\n name?: string\n sort?: SortableLocationField\n page?: number\n per_page?: number\n}\n\n/**\n * Locations API\n *\n * Datacenters are organized by Locations. Datacenters in the same Location are connected with very low latency links.\n * https://docs.hetzner.cloud/#locations\n *\n */\nexport class Locations extends BaseAPI {\n /**\n * List all locations with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListLocationsParams,\n ): Promise<\n { success: true; response: LocationsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<LocationsResponse>(`/locations${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Get a specific location by ID\n * @param id The location ID\n */\n async get(\n id: number,\n ): Promise<{ success: true; response: Location } | { success: false; response: APIError }> {\n return this.request<Location>(`/locations/${id}`)\n }\n}\n\nexport class Datacenters extends BaseAPI {\n /**\n * List all datacenters with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListLocationsParams,\n ): Promise<\n { success: true; response: DatacentersResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<DatacentersResponse>(`/datacenters${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Get a specific datacenter by ID\n * @param id The datacenter ID\n */\n async get(\n id: number,\n ): Promise<{ success: true; response: Datacenter } | { success: false; response: APIError }> {\n return this.request<Datacenter>(`/datacenters/${id}`)\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError, BaseAction } from \"../types\"\nimport type {\n AddRouteNetworkParams,\n AddSubnetNetworkParams,\n ChangeIPRangeNetworkParams,\n ChangeProtectionNetworkParams,\n DeleteRouteNetworkParams,\n DeleteSubnetNetworkParams,\n NetworkActionsResponse,\n ListNetworkActionsParams,\n} from \"./types\"\n\n/**\n * Network Actions API\n *\n * Network actions are used to manage networks.\n * https://docs.hetzner.cloud/#networks-actions\n *\n */\nexport class NetworkActions extends BaseAPI {\n /**\n * List all actions for Networks\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListNetworkActionsParams,\n ): Promise<\n { success: true; response: NetworkActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<NetworkActionsResponse>(\n `/networks/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for Networks\n * @param actionId The action ID\n */\n async get(\n actionId: number,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/actions/${actionId}`)\n }\n\n /**\n * List actions for a specific Network\n * @param networkId The Network ID\n * @param params Optional parameters for filtering and pagination\n */\n async listForNetwork(\n networkId: number,\n params?: ListNetworkActionsParams,\n ): Promise<\n { success: true; response: NetworkActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<NetworkActionsResponse>(\n `/networks/${networkId}/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for a specific Network\n * @param networkId The Network ID\n * @param actionId The action ID\n */\n async getForNetwork(\n networkId: number,\n actionId: number,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/${actionId}`)\n }\n\n /**\n * Add a route to a Network\n * @param networkId The Network ID\n * @param params Parameters for adding the route\n */\n async addRoute(\n networkId: number,\n params: AddRouteNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/add_route`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a route from a Network\n * @param networkId The Network ID\n * @param params Parameters for deleting the route\n */\n async deleteRoute(\n networkId: number,\n params: DeleteRouteNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/delete_route`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Add a subnet to a Network\n * @param networkId The Network ID\n * @param params Parameters for adding the subnet\n */\n async addSubnet(\n networkId: number,\n params: AddSubnetNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/add_subnet`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a subnet from a Network\n * @param networkId The Network ID\n * @param params Parameters for deleting the subnet\n */\n async deleteSubnet(\n networkId: number,\n params: DeleteSubnetNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/delete_subnet`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Change the IP range of a Network\n * @param networkId The Network ID\n * @param params Parameters for changing the IP range\n */\n async changeIPRange(\n networkId: number,\n params: ChangeIPRangeNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(`/networks/${networkId}/actions/change_ip_range`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Change the protection status of a Network\n * @param networkId The Network ID\n * @param params Parameters for changing the protection status\n */\n async changeProtection(\n networkId: number,\n params: ChangeProtectionNetworkParams,\n ): Promise<\n { success: true; response: { actions: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ actions: BaseAction }>(\n `/networks/${networkId}/actions/change_protection`,\n {\n method: \"POST\",\n body: JSON.stringify(params),\n },\n )\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport { NetworkActions } from \"./actions\"\nimport type {\n CreateNetworkParams,\n ListNetworksParams,\n Network,\n NetworksResponse,\n UpdateNetworkParams,\n} from \"./types\"\n\n/**\n * Networks API\n *\n * Networks is a private networks feature. These Networks are optional and they coexist with the public network that every Server has by default.\n * https://docs.hetzner.cloud/#networks\n *\n */\nexport class Networks extends BaseAPI {\n private _actions: NetworkActions | null = null\n\n /**\n * List all Networks with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListNetworksParams,\n ): Promise<\n { success: true; response: NetworksResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<NetworksResponse>(`/networks${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Create a new Network\n * @param params Parameters for creating the Network\n */\n async create(\n params: CreateNetworkParams,\n ): Promise<\n { success: true; response: { network: Network } } | { success: false; response: APIError }\n > {\n return this.request<{ network: Network }>(\"/networks\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Get a specific Network by ID\n * @param id The Network ID\n */\n async get(\n id: number,\n ): Promise<\n { success: true; response: { network: Network } } | { success: false; response: APIError }\n > {\n return this.request<{ network: Network }>(`/networks/${id}`)\n }\n\n /**\n * Update a Network's properties\n * @param id The Network ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateNetworkParams,\n ): Promise<\n { success: true; response: { network: Network } } | { success: false; response: APIError }\n > {\n return this.request<{ network: Network }>(`/networks/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a Network\n * @param id The Network ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/networks/${id}`, {\n method: \"DELETE\",\n })\n }\n\n get actions(): NetworkActions {\n if (!this._actions) {\n this._actions = new NetworkActions(this.token)\n }\n return this._actions\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type { CertificateActionsResponse, CertificateActionResponse } from \"./types\"\n\nexport interface ListCertificateActionsParams {\n id?: number[]\n sort?: Array<\n | \"id\"\n | \"command\"\n | \"status\"\n | \"started\"\n | \"finished\"\n | \"id:asc\"\n | \"id:desc\"\n | \"command:asc\"\n | \"command:desc\"\n | \"status:asc\"\n | \"status:desc\"\n | \"started:asc\"\n | \"started:desc\"\n | \"finished:asc\"\n | \"finished:desc\"\n >\n status?: Array<\"running\" | \"success\" | \"error\">\n page?: number\n per_page?: number\n}\n\n/**\n * Certificate Actions API\n *\n * Actions are the individual operations that can be performed on a certificate.\n * https://docs.hetzner.cloud/#certificate-actions\n *\n */\nexport class CertificateActions extends BaseAPI {\n /**\n * Get all actions for all certificates\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListCertificateActionsParams,\n ): Promise<\n { success: true; response: CertificateActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<CertificateActionsResponse>(\n `/certificates/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action\n * @param actionId The action ID\n */\n async get(\n actionId: number,\n ): Promise<\n { success: true; response: CertificateActionResponse } | { success: false; response: APIError }\n > {\n return this.request<CertificateActionResponse>(`/certificates/actions/${actionId}`)\n }\n\n /**\n * Get all actions for a specific certificate\n * @param certificateId The certificate ID\n * @param params Optional parameters for filtering and pagination\n */\n async listForCertificate(\n certificateId: number,\n params?: Omit<ListCertificateActionsParams, \"id\">,\n ): Promise<\n { success: true; response: CertificateActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<CertificateActionsResponse>(\n `/certificates/${certificateId}/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for a certificate\n * @param certificateId The certificate ID\n * @param actionId The action ID\n */\n async getForCertificate(\n certificateId: number,\n actionId: number,\n ): Promise<\n { success: true; response: CertificateActionResponse } | { success: false; response: APIError }\n > {\n return this.request<CertificateActionResponse>(\n `/certificates/${certificateId}/actions/${actionId}`,\n )\n }\n\n /**\n * Retry issuance or renewal of a certificate\n * @param certificateId The certificate ID\n */\n async retry(\n certificateId: number,\n ): Promise<\n { success: true; response: CertificateActionResponse } | { success: false; response: APIError }\n > {\n return this.request<CertificateActionResponse>(`/certificates/${certificateId}/actions/retry`, {\n method: \"POST\",\n })\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport { CertificateActions } from \"./actions\"\nimport type {\n Certificate,\n CertificatesResponse,\n CreateCertificateParams,\n UpdateCertificateParams,\n} from \"./types\"\n\nexport interface ListCertificatesParams {\n name?: string\n label_selector?: string\n sort?: \"id\" | \"id:asc\" | \"id:desc\" | \"name\" | \"name:asc\" | \"name:desc\"\n page?: number\n per_page?: number\n}\n\nexport class Certificates extends BaseAPI {\n private _actions: CertificateActions | null = null\n\n /**\n * List all certificates with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListCertificatesParams,\n ): Promise<\n { success: true; response: CertificatesResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<CertificatesResponse>(\n `/certificates${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific certificate by ID\n * @param id The certificate ID\n */\n async get(\n id: number,\n ): Promise<{ success: true; response: Certificate } | { success: false; response: APIError }> {\n return this.request<Certificate>(`/certificates/${id}`)\n }\n\n /**\n * Create a new certificate\n * @param params Parameters for creating the certificate\n */\n async create(\n params: CreateCertificateParams,\n ): Promise<{ success: true; response: Certificate } | { success: false; response: APIError }> {\n return this.request<Certificate>(\"/certificates\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Update a certificate's properties\n * @param id The certificate ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateCertificateParams,\n ): Promise<{ success: true; response: Certificate } | { success: false; response: APIError }> {\n return this.request<Certificate>(`/certificates/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a certificate\n * @param id The certificate ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/certificates/${id}`, {\n method: \"DELETE\",\n })\n }\n\n get actions(): CertificateActions {\n if (!this._actions) {\n this._actions = new CertificateActions(this.token)\n }\n return this._actions\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type { SSHKey, SSHKeysResponse, CreateSSHKeyParams, UpdateSSHKeyParams } from \"./types\"\nexport * from \"./certificates\"\nexport * from \"./actions\"\n\nexport interface ListSSHKeysParams {\n name?: string\n fingerprint?: string\n label_selector?: string\n sort?: \"id\" | \"id:asc\" | \"id:desc\" | \"name\" | \"name:asc\" | \"name:desc\"\n page?: number\n per_page?: number\n}\n\n/**\n * SSH Keys API\n *\n * SSH keys are used to authenticate with the server.\n * https://docs.hetzner.cloud/#ssh-keys\n *\n */\nexport class SSHKeys extends BaseAPI {\n /**\n * List all SSH keys with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListSSHKeysParams,\n ): Promise<\n { success: true; response: SSHKeysResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.append(key, value.toString())\n }\n })\n }\n\n const queryString = queryParams.toString()\n return this.request<SSHKeysResponse>(`/ssh_keys${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Get a specific SSH key by ID\n * @param id The SSH key ID\n */\n async get(\n id: number,\n ): Promise<{ success: true; response: { ssh_key: SSHKey } } | { success: false; response: APIError }> {\n return this.request<{ ssh_key: SSHKey }>(`/ssh_keys/${id}`)\n }\n\n /**\n * Create a new SSH key\n * @param params Parameters for creating the SSH key\n */\n async create(\n params: CreateSSHKeyParams,\n ): Promise<{ success: true; response: { ssh_key: SSHKey } } | { success: false; response: APIError }> {\n return this.request<{ ssh_key: SSHKey }>(\"/ssh_keys\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Update an SSH key's properties\n * @param id The SSH key ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateSSHKeyParams,\n ): Promise<{ success: true; response: { ssh_key: SSHKey } } | { success: false; response: APIError }> {\n return this.request<{ ssh_key: SSHKey }>(`/ssh_keys/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete an SSH key\n * @param id The SSH key ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/ssh_keys/${id}`, {\n method: \"DELETE\",\n })\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError, BaseAction } from \"../types\"\nimport type {\n AttachVolumeParams,\n ChangeVolumeProtectionParams,\n ListVolumeActionsParams,\n ResizeVolumeParams,\n VolumeActionsResponse,\n} from \"./types\"\n\nexport class VolumeActions extends BaseAPI {\n /**\n * List all actions for Volumes (globally, not for a specific volume)\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListVolumeActionsParams,\n ): Promise<\n { success: true; response: VolumeActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else {\n queryParams.append(key, value.toString())\n }\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<VolumeActionsResponse>(\n `/volumes/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for Volumes (globally)\n * @param actionId The action ID\n */\n async getGlobalAction(\n actionId: number,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n // Assuming a /volumes/actions/{id} endpoint, adjust if different\n return this.request<{ action: BaseAction }>(`/volumes/actions/${actionId}`)\n }\n\n /**\n * List actions for a specific Volume\n * @param volumeId The Volume ID\n * @param params Optional parameters for filtering and pagination\n */\n async listForVolume(\n volumeId: number,\n params?: ListVolumeActionsParams,\n ): Promise<\n { success: true; response: VolumeActionsResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else {\n queryParams.append(key, value.toString())\n }\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<VolumeActionsResponse>(\n `/volumes/${volumeId}/actions${queryString ? `?${queryString}` : \"\"}`,\n )\n }\n\n /**\n * Get a specific action for a specific Volume\n * @param volumeId The Volume ID\n * @param actionId The action ID\n */\n async getAction(\n volumeId: number,\n actionId: number,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: BaseAction }>(`/volumes/${volumeId}/actions/${actionId}`)\n }\n\n /**\n * Attach a Volume to a Server\n * @param volumeId The Volume ID\n * @param params Parameters for attaching the volume\n */\n async attach(\n volumeId: number,\n params: AttachVolumeParams,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: BaseAction }>(`/volumes/${volumeId}/actions/attach`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Detach a Volume from a Server\n * @param volumeId The Volume ID\n */\n async detach(\n volumeId: number,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: BaseAction }>(`/volumes/${volumeId}/actions/detach`, {\n method: \"POST\",\n })\n }\n\n /**\n * Resize a Volume\n * @param volumeId The Volume ID\n * @param params Parameters for resizing the volume\n */\n async resize(\n volumeId: number,\n params: ResizeVolumeParams,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: BaseAction }>(`/volumes/${volumeId}/actions/resize`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Change Volume Protection\n * @param volumeId The Volume ID\n * @param params Parameters for changing the protection status\n */\n async changeProtection(\n volumeId: number,\n params: ChangeVolumeProtectionParams,\n ): Promise<\n { success: true; response: { action: BaseAction } } | { success: false; response: APIError }\n > {\n return this.request<{ action: BaseAction }>(`/volumes/${volumeId}/actions/change_protection`, {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError, BaseAction } from \"../types\"\nimport { VolumeActions } from \"./actions\"\nimport type {\n CreateVolumeParams,\n ListVolumesParams,\n UpdateVolumeParams,\n Volume,\n VolumesResponse,\n} from \"./types\"\n\n/**\n * Volumes API\n *\n * Volumes can be used to store data on a server.\n * https://docs.hetzner.cloud/#volumes\n *\n */\nexport class Volumes extends BaseAPI {\n private _actions: VolumeActions | null = null\n\n /**\n * List all Volumes with optional filtering and pagination\n * @param params Optional parameters for filtering and pagination\n */\n async getAll(\n params?: ListVolumesParams,\n ): Promise<\n { success: true; response: VolumesResponse } | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else {\n queryParams.append(key, value.toString())\n }\n }\n })\n }\n const queryString = queryParams.toString()\n return this.request<VolumesResponse>(`/volumes${queryString ? `?${queryString}` : \"\"}`)\n }\n\n /**\n * Get a specific Volume by ID\n * @param id The Volume ID\n */\n async get(\n id: number,\n ): Promise<\n { success: true; response: { volume: Volume } } | { success: false; response: APIError }\n > {\n return this.request<{ volume: Volume }>(`/volumes/${id}`)\n }\n\n /**\n * Create a new Volume\n * @param params Parameters for creating the Volume\n */\n async create(\n params: CreateVolumeParams,\n ): Promise<\n | { success: true; response: { volume: Volume; action?: BaseAction } }\n | { success: false; response: APIError }\n > {\n // The API might return an action object along with the volume upon creation\n return this.request<{ volume: Volume; action?: BaseAction }>(\"/volumes\", {\n method: \"POST\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Update a Volume's properties\n * @param id The Volume ID\n * @param params Parameters to update\n */\n async update(\n id: number,\n params: UpdateVolumeParams,\n ): Promise<\n { success: true; response: { volume: Volume } } | { success: false; response: APIError }\n > {\n return this.request<{ volume: Volume }>(`/volumes/${id}`, {\n method: \"PUT\",\n body: JSON.stringify(params),\n })\n }\n\n /**\n * Delete a Volume\n * @param id The Volume ID\n */\n async delete(\n id: number,\n ): Promise<{ success: true; response: null } | { success: false; response: APIError }> {\n return this.request<null>(`/volumes/${id}`, {\n method: \"DELETE\",\n })\n }\n\n get actions(): VolumeActions {\n if (!this._actions) {\n this._actions = new VolumeActions(this.token)\n }\n return this._actions\n }\n}\n","import { BaseAPI } from \"../base\"\nimport type { APIError } from \"../types\"\nimport type {\n AddServiceLoadBalancerParams,\n AddTargetLoadBalancerParams,\n AttachToNetworkLoadBalancerParams,\n ChangeAlgorithmLoadBalancerParams,\n ChangeDNSPTRLoadBalancerParams,\n ChangeProtectionLoadBalancerParams,\n ChangeTypeLoadBalancerParams,\n DeleteServiceLoadBalancerParams,\n DetachFromNetworkLoadBalancerParams,\n ListLoadBalancerActionsParams,\n LoadBalancerActionResponse, // For single action responses\n LoadBalancerActionsResponse, // For list action responses\n RemoveTargetLoadBalancerParams,\n UpdateServiceLoadBalancerParams,\n} from \"./types\"\n\n/**\n * Load Balancer Actions API\n *\n * Load balancer actions are used to manage load balancers.\n * https://docs.hetzner.cloud/#load-balancers-actions\n *\n */\nexport class LoadBalancerActions extends BaseAPI {\n /**\n * List all global actions for Load Balancers\n * @param params Optional parameters for filtering and pagination\n */\n async getAllGlobal(\n params?: ListLoadBalancerActionsParams,\n ): Promise<\n | { success: true; response: LoadBalancerActionsResponse }\n | { success: false; response: APIError }\n > {\n const queryParams = new URLSearchParams()\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined) {\n if (Array.isArray(value)) {\n value.forEach((v) => queryParams.append(key, v.toString()))\n } else {\n queryParams.append(key, value.toString(