UNPKG

@urixen/ptero-connect

Version:

The only package you need for Pterodactyl API management.

1,093 lines (1,084 loc) 40.2 kB
/** * @ignore */ function removeTrailingSlash(url) { return url.endsWith("/") && url.length > 1 ? url.slice(0, -1) : url; } /** * @includeExample ./examples/ApplicationApi.example.ts * * @author nehxurai */ export class ApplicationApi { panelUrl; apiKey; customHeaders; /** * @param panelUrl - The base URL of the panel API. * @param apiKey - The API key for authentication. * @param customHeaders - Optional custom headers to include in requests. */ constructor(panelUrl, apiKey, customHeaders) { this.panelUrl = removeTrailingSlash(panelUrl); this.apiKey = apiKey; this.customHeaders = customHeaders; } getHeaders() { const baseHeaders = { Accept: "application/json", Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json", }; return { ...baseHeaders, ...(this.customHeaders || {}), }; } async fetchJson(url, options) { const response = await fetch(url, options); if (!response.ok) { throw new Error(`API request failed: ${response.status}, ${response.statusText}`); } return response.json(); } /** * Get all users from panel * @includeExample ./examples/getAllUser.example.ts */ async getAllUser() { const data = await this.fetchJson(`${this.panelUrl}/api/application/users`, { headers: this.getHeaders() }); return data.data; } /** * Get a user by email * @param email User's email * @includeExample ./examples/getUserByEmail.example.ts */ async getAUserByEmail(email) { const data = await this.fetchJson(`${this.panelUrl}/api/application/users?filter[email]=${encodeURIComponent(email)}`, { headers: this.getHeaders() }); if (data.data.length === 0) throw new Error(`User with email ${email} not found.`); return data.data[0]; } /** * Get a user by username * @param username User's username * @includeExample ./examples/getAUserByUsername.example.ts */ async getAUserByUsername(username) { const data = await this.fetchJson(`${this.panelUrl}/api/application/users?filter[username]=${encodeURIComponent(username)}`, { headers: this.getHeaders() }); if (data.data.length === 0) throw new Error(`User with username ${username} not found.`); return data.data[0]; } /** * Get a user by ID * @param id User's ID * @includeExample ./examples/getAUserById.example.ts */ async getAUserById(id) { const data = await this.fetchJson(`${this.panelUrl}/api/application/users/${id}`, { headers: this.getHeaders() }); return data.data; } /** * Create a new user * @param user User creation data * @includeExample ./examples/createAUser.example.ts */ async createUser(user) { const data = await this.fetchJson(`${this.panelUrl}/api/application/users`, { method: "POST", headers: this.getHeaders(), body: JSON.stringify(user), }); return data.data; } /** * Update a user * @param id User ID * @param updates Fields to update * @includeExample ./examples/updateUser.example.ts */ async updateUser(id, updates) { const data = await this.fetchJson(`${this.panelUrl}/api/application/users/${id}`, { method: "PATCH", headers: this.getHeaders(), body: JSON.stringify(updates), }); return data.data; } /** * Delete a user by ID * @param id User ID * @includeExample ./examples/deleteUser.example.ts */ async deleteUser(id) { const response = await fetch(`${this.panelUrl}/api/application/users/${id}`, { method: "DELETE", headers: this.getHeaders(), }); if (!response.ok) { throw new Error(`Failed to delete user: ${response.status}, ${response.statusText}`); return false; } return true; } /** * Get all Servers * @param filter set a filter * @param value set value of the filter */ async getAllServers(filter, value) { const url = this.panelUrl + "/api/application/servers" + (filter ? `?filter[${filter}]=${value}` : ""); const response = await fetch(url, { method: "GET", headers: this.getHeaders(), }); if (!response.ok) { throw new Error(`Failed to fetch all servers: ${response.status}, ${response.statusText}`); } const data = await response.json(); return data.data; } /** * Retrieve detailed information about a specific server. * @param id Server Id * @param include Include relationships (allocations, user, subusers, pack, nest, egg, variables, location, node, databases, backups) */ async getAServerById(id, include) { const url = this.panelUrl + `/api/application/servers/${id}?include=${include}`; const response = await fetch(url, { method: "GET", headers: this.getHeaders(), }); if (!response.ok) { throw new Error(`Failed to fetch server:${response.status}, ${response.statusText}`); } const data = await response.json(); return data; } /** * create a server * @param data - Server Data for creation */ async createServer({ name, user, egg, docker_image, startup, enviroment, limits, feature_limits, allocation, deploy, }) { const url = this.panelUrl + "/api/application/servers/"; const response = await fetch(url, { method: "POST", headers: this.getHeaders(), body: JSON.stringify({ name, user, egg, docker_image, startup, enviroment, limits, feature_limits, allocation, deploy, }), }); if (!response.ok) { throw new Error(`Error creating server: ${response.status}, ${response.statusText}`); return false; } const data = response.json(); return { created: true, data }; } /** * Updates a server's details via the panel API. * * @param id - The ID of the server to update. * @param updatedData - An object containing the updated server fields. * @returns The updated server object. * @throws Will throw an error if the request fails. */ async updateServerDetails(id, updatedData) { const url = `${this.panelUrl}/api/application/servers/${id}/details`; const response = await fetch(url, { method: "PATCH", headers: this.getHeaders(), body: JSON.stringify(updatedData), }); if (!response.ok) { const errorText = await response.text().catch(() => ""); throw new Error(`Unable to update server details: ${response.status} ${response.statusText}\n${errorText}`); } const data = await response.json(); return data; } /** * Suspend a server * @param id Server id */ async suspendServer(id) { const url = `${this.panelUrl}/api/application/servers/${id}/suspend`; const response = await fetch(url, { method: "POST", headers: this.getHeaders(), }); if (!response.ok) throw new Error(`cannot suspend the server: ${response.status}`); return true; } /** * Remove suspension from a server to allow it to start. * @param id Server id */ async unSuspendServer(id) { const url = `${this.panelUrl}/api/application/servers/${id}/unsuspend`; const response = await fetch(url, { method: "POST", headers: this.getHeaders(), }); if (!response.ok) throw new Error(`cannot unsuspend the server: ${response.status}`); return true; } /** * Update Server Build Configuration * Update server resource limits and feature limits. * * PATCH /api/application/servers/{server}/build * * @param id - Server ID * @param buildData - Build configuration object * @returns Updated server object */ async updateServerBuild(id, buildData) { const url = `${this.panelUrl}/api/application/servers/${id}/build`; const response = await fetch(url, { method: "PATCH", headers: this.getHeaders(), body: JSON.stringify(buildData), }); if (!response.ok) { const errorText = await response.text().catch(() => ""); throw new Error(`Unable to update server build: ${response.status} ${response.statusText}\n${errorText}`); } return response.json(); } /** * Updates server start up settings * * PATCH /api/application/servers/{id}/startup * * @param id - Server id * @param updatedData - updated server start up settings * @returns updated Server setting data */ async updateServerStartup(id, updatedData) { const url = `${this.panelUrl}/api/application/servers/${id}/startup`; const res = await fetch(url, { method: "PATCH", headers: this.getHeaders(), body: JSON.stringify(updatedData), }); if (!res.ok) throw new Error(`Error updating startup: ${res.status}, ${await res.text()}`); const data = await res.json(); return data; } /** * Reinstall the corresponding server * * POST /api/application/servers/{id}/reinstall * * @param id - Server Id * @return boolean */ async reinstallServer(id) { const url = `${this.panelUrl}/api/application/servers/${id}/reinstall`; const res = await fetch(url, { method: "POST", headers: this.getHeaders(), }); if (!res.ok) return false; return true; } /** * Delete a server * * DELETE /api/application/servers/{id} * * @param id - server id * @param force - force delete server (may damage wings) * @returns boolean */ async deleteServer(id, force = false) { const res = await fetch(`${this.panelUrl}/api/application/servers/${id}?force=${force}`, { method: "DELETE", }); if (!res.ok) return false; return true; } /** * Manage server databases through the Application API for administrative control. */ /** * get corresponding server databases * * GET /api/application/servers/{id}/databases * * @param id - server id * @return server databases */ async getServerDbs(id) { const url = `${this.panelUrl}/api/application/servers/${id}/databases`; const res = await fetch(url, { headers: this.getHeaders(), }); if (!res.ok) throw new Error(`failed to fetch databases for server ${id}: ${res.status}, ${await res.text()}`); const data = await res.json(); return data.data; } /** * get a server's database details * * GET /api/application/servers/{id}/databases/{dbId} * * @param id - server id * @param dbID - database id * @returns database details */ async getServerDB(id, dbID) { const url = `${this.panelUrl}/api/application/servers/${id}/databases/${dbID}`; const res = await fetch(url, { headers: this.getHeaders(), }); if (!res.ok) throw new Error(`failed to fetch database for server ${id}: ${res.status}, ${await res.text()}`); const data = await res.json(); return data; } /** * Create a new database * * POST /api/application/servers/{id}/databases * * @param id - server id * @param dataDB - database details * @returns database */ async createServerDB(id, dataDB) { const url = `${this.panelUrl}/api/application/servers/${id}/databases`; const res = await fetch(url, { headers: this.getHeaders(), method: "POST", body: JSON.stringify(dataDB), }); if (!res.ok) throw new Error(`failed to create database for server ${id}: ${res.status}, ${await res.text()}`); const data = await res.json(); return data; } /** * update server database details * * PATCH /api/application/servers/{id}/databases/{dbID} * * @param id - server id * @param dbID - database id * @param dataDB - data to be updated * @returns database details */ async updateServerDB(id, dbID, dataDB) { const url = `${this.panelUrl}/api/application/servers/${id}/databases/${dbID}`; const res = await fetch(url, { headers: this.getHeaders(), method: "PATCH", body: JSON.stringify(dataDB), }); if (!res.ok) throw new Error(`failed to update database for server ${id}: ${res.status}, ${await res.text()}`); const data = await res.json(); return data; } async resetServerDB(id, dbID) { const url = `${this.panelUrl}/api/application/servers/${id}/databases/${dbID}/reset-password`; const res = await fetch(url, { headers: this.getHeaders(), method: "POST", }); if (!res.ok) throw new Error(`failed to reset database password for server ${id}: ${res.status}, ${await res.text()}`); const data = await res.json(); return data; } /** * delete a database from server * * DELETE /api/application/servers/{id}/databases/{dbID} * * @param id - server id * @param dbID - database id * @returns boolean */ async deleteServerDB(id, dbID) { const url = `${this.panelUrl}/api/application/servers/${id}/databases/${dbID}`; const res = await fetch(url, { headers: this.getHeaders(), method: "DELETE", }); if (!res.ok) throw new Error(`failed to delete database for server ${id}: ${res.status}, ${await res.text()}`); return true; } async getAllNodes(options = {}) { const params = new URLSearchParams(options); const response = await fetch(`${this.panelUrl}/api/application/nodes?${params}`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch all nodes: ${response.status}, ${await response.text()}`); const { data } = await response.json(); return data; } async createNode(nodeData) { const response = await fetch(`${this.panelUrl}/api/application/nodes`, { method: "POST", headers: this.getHeaders(), body: JSON.stringify(nodeData), }); return (await response.json()); } async getNodeConfiguration(nodeId) { const response = await fetch(`${this.panelUrl}/api/application/nodes/${nodeId}/configuration`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch node config node: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } async getAllAllocation(nodeId) { const response = await fetch(`${this.panelUrl}/api/application/nodes/${nodeId}/allocations`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch node allocations: ${response.status}, ${await response.text()}`); const { data } = await response.json(); return data; } async createAllocations(nodeId, allocationData) { const response = await fetch(`${this.panelUrl}/api/application/nodes/${nodeId}/allocations`, { method: "POST", headers: this.getHeaders(), body: JSON.stringify(allocationData), }); return response.status === 204; } async deleteNode(nodeId) { const response = await fetch(`${this.panelUrl}/api/application/nodes/${nodeId}`, { method: "DELETE", headers: this.getHeaders(), }); return response.status === 204; } async getAllLocations(options = {}) { const params = new URLSearchParams(options); const response = await fetch(`${this.panelUrl}/api/application/locations?${params}`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch loactions: ${response.status}, ${await response.text()}`); const { data } = await response.json(); return data; } async createLocation(locationData) { const response = await fetch(`${this.panelUrl}/api/application/locations`, { method: "POST", headers: this.getHeaders(), body: JSON.stringify(locationData), }); if (!response.ok) throw new Error(`Failed to create locations: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } async updateLocation(locationId, updateData) { const response = await fetch(`${this.panelUrl}/api/application/locations/${locationId}`, { method: "PATCH", headers: this.getHeaders(), body: JSON.stringify(updateData), }); if (!response.ok) throw new Error(`Failed to update location: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } async deleteLocation(locationId) { const response = await fetch(`${this.panelUrl}/api/application/locations/${locationId}`, { method: "DELETE", headers: this.getHeaders(), }); return response.status === 204; } async getLocationWithNodes(locationId) { const response = await fetch(`${this.panelUrl}/api/application/locations/${locationId}?include=nodes`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch location with nodes: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } /** * get all nests * @param options - additional options */ async getAllNests(options = {}) { const params = new URLSearchParams(options); const response = await fetch(`${this.panelUrl}/api/application/nests?${params}`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch nests: ${response.status}, ${await response.text()}`); const { data } = await response.json(); return data; } /** * get a nest * * @param nestId - nest id */ async getANest(nestId) { const response = await fetch(`${this.panelUrl}/api/application/nests/${nestId}`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch nests: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } /** * get all eggs * * @param nestId - nest id */ async getAllEggs(nestId) { const response = await fetch(`${this.panelUrl}/api/application/nests/${nestId}/eggs`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch nests: ${response.status}, ${await response.text()}`); const { data } = await response.json(); return data; } /** * get a egg * * @param nestId - nest id * @param eggId - egg id */ async getAEgg(nestId, eggId) { const response = await fetch(`${this.panelUrl}/api/application/nests/${nestId}/eggs/${eggId}`, { headers: this.getHeaders(), }); if (!response.ok) throw new Error(`Failed to fetch nests: ${response.status}, ${await response.text()}`); const data = await response.json(); return data; } getEggById(eggId) { throw new Error("Small Utility not loaded"); } getNodesByLocationId(locationId) { throw new Error("Small Utility not loaded"); } } /** * * CLIENT API SECTION * */ /** * loads all small utilities available * getEggById * getNodesByLocationId */ export function smallUtility() { /** * Find egg by ID across all nests * @param {number|string} eggId - The egg ID to find * @returns {Promise<Object>} - The egg attributes * @throws {Error} - If egg is not found */ // @ts-ignore ApplicationApi.prototype.getEggById = async function (eggId) { try { const nests = await this.getAllNests(); const api = this; for (const nest of nests) { const nestId = nest.attributes.id; try { const eggs = await api.getAllEggs(nestId); const match = eggs.find((e) => e.attributes.id == eggId); if (match) { console.log(`Found egg ${eggId} in nest ${nestId}`); return match; } } catch (error) { console.warn(`Failed to fetch eggs for nest ${nestId}:`); continue; } } throw new Error(`Egg with ID ${eggId} not found in any nest`); } catch (error) { console.error("Error finding egg:", error); throw new Error("Failed to locate egg configuration"); } }; /** * fetch all nodes in a location by location id * * @param locationId - location id */ // @ts-ignore ApplicationApi.prototype.getNodesByLocationId = async function (locationId) { const api = this; try { let nodes = []; const response = await api.getAllNodes(); response.forEach((node) => { if (node.attributes.location_id === locationId) { nodes.push(node); } }); } catch (error) { throw new Error(`something went wrong: ${error}`); } }; } // Custom error classes for better error handling export class PterodactylAPIError extends Error { status; statusText; responseBody; constructor(message, status, statusText, responseBody) { super(message); this.status = status; this.statusText = statusText; this.responseBody = responseBody; this.name = 'PterodactylAPIError'; } } export class ValidationError extends PterodactylAPIError { constructor(message, responseBody) { super(`Request validation failed: ${message}`, 400, 'Bad Request', responseBody); this.name = 'ValidationError'; } } export class AuthenticationError extends PterodactylAPIError { constructor() { super('Invalid credentials', 401, 'Unauthorized'); this.name = 'AuthenticationError'; } } export class PermissionError extends PterodactylAPIError { constructor(message, responseBody) { super(`Insufficient permission: ${message}`, 403, 'Forbidden', responseBody); this.name = 'PermissionError'; } } // Enum for common permissions export var ServerPermissions; (function (ServerPermissions) { ServerPermissions["CONTROL_CONSOLE"] = "control.console"; ServerPermissions["CONTROL_START"] = "control.start"; ServerPermissions["CONTROL_STOP"] = "control.stop"; ServerPermissions["CONTROL_RESTART"] = "control.restart"; ServerPermissions["USER_CREATE"] = "user.create"; ServerPermissions["USER_READ"] = "user.read"; ServerPermissions["USER_UPDATE"] = "user.update"; ServerPermissions["USER_DELETE"] = "user.delete"; ServerPermissions["FILE_CREATE"] = "file.create"; ServerPermissions["FILE_READ"] = "file.read"; ServerPermissions["FILE_UPDATE"] = "file.update"; ServerPermissions["FILE_DELETE"] = "file.delete"; ServerPermissions["FILE_ARCHIVE"] = "file.archive"; ServerPermissions["FILE_SFTP"] = "file.sftp"; ServerPermissions["ALLOCATION_READ"] = "allocation.read"; ServerPermissions["ALLOCATION_CREATE"] = "allocation.create"; ServerPermissions["ALLOCATION_UPDATE"] = "allocation.update"; ServerPermissions["ALLOCATION_DELETE"] = "allocation.delete"; ServerPermissions["STARTUP_READ"] = "startup.read"; ServerPermissions["STARTUP_UPDATE"] = "startup.update"; ServerPermissions["DATABASE_CREATE"] = "database.create"; ServerPermissions["DATABASE_READ"] = "database.read"; ServerPermissions["DATABASE_UPDATE"] = "database.update"; ServerPermissions["DATABASE_DELETE"] = "database.delete"; ServerPermissions["SCHEDULE_CREATE"] = "schedule.create"; ServerPermissions["SCHEDULE_READ"] = "schedule.read"; ServerPermissions["SCHEDULE_UPDATE"] = "schedule.update"; ServerPermissions["SCHEDULE_DELETE"] = "schedule.delete"; ServerPermissions["BACKUP_CREATE"] = "backup.create"; ServerPermissions["BACKUP_READ"] = "backup.read"; ServerPermissions["BACKUP_DELETE"] = "backup.delete"; ServerPermissions["BACKUP_DOWNLOAD"] = "backup.download"; ServerPermissions["SETTINGS_RENAME"] = "settings.rename"; ServerPermissions["SETTINGS_REINSTALL"] = "settings.reinstall"; })(ServerPermissions || (ServerPermissions = {})); /** * Pterodactyl Panel Client API * A comprehensive TypeScript client for interacting with the Pterodactyl Panel API * * @author vspcoder */ export class ClientApi { panelUrl; clientKey; headers; debug; timeout; constructor(panelUrl, clientKey, options = {}) { this.panelUrl = removeTrailingSlash(panelUrl); this.clientKey = clientKey; this.debug = options.debug ?? false; this.timeout = options.timeout ?? 30000; // 30 seconds default this.headers = { Accept: "application/json", Authorization: `Bearer ${this.clientKey}`, "Content-Type": "application/json", ...options.headers, }; } async api(url, data, method) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const fetchOptions = { headers: this.headers, method: method ?? (data ? "POST" : "GET"), body: data ? typeof data === "string" ? data : JSON.stringify(data) : undefined, signal: controller.signal, }; if (this.debug) { console.time("request_time"); console.log(`[Req] [${url}]: ${JSON.stringify(fetchOptions)}`); } const response = await fetch(this.panelUrl + url, fetchOptions); if (this.debug) { console.timeEnd("request_time"); } if (!response.ok) { const errorText = await response.text(); switch (response.status) { case 400: throw new ValidationError(errorText); case 401: throw new AuthenticationError(); case 403: throw new PermissionError(errorText); case 422: throw new ValidationError(`Invalid request data: ${errorText}`, errorText); default: throw new PterodactylAPIError(`API Error: ${response.status} ${response.statusText}`, response.status, response.statusText, errorText); } } if (response.headers.get("Content-Type")?.includes("application/json")) { const jsonResponse = await response.json(); if (this.debug) console.log(`[Res] [${url}]:`, jsonResponse); return jsonResponse; } else { const textResponse = await response.text(); if (this.debug) console.log(`[Res] [${url}]:`, textResponse); return textResponse; } } catch (error) { if (error instanceof Error && error.name === 'AbortError') { throw new PterodactylAPIError('Request timeout', 408, 'Request Timeout'); } if (this.debug) console.error(`[Error] [${url}]:`, error); throw error; } finally { clearTimeout(timeoutId); } } // Account Management Methods async getUserDetails() { return this.api("/api/client/account"); } async getTwoFAQRCode() { return this.api("/api/client/account/two-factor"); } async enableTwoFA(code) { return this.api("/api/client/account/two-factor", { code: String(code) }, "POST"); } async disableTwoFA(password) { return this.api("/api/client/account/two-factor", { password }, "DELETE"); } async updateEmail(newEmail, password) { await this.api("/api/client/account/email", { email: newEmail, password }, "PUT"); } async updatePassword(currentPassword, newPassword) { await this.api("/api/client/account/password", { current_password: currentPassword, password: newPassword, password_confirmation: newPassword, }, "PUT"); } // API Key Management async listAPIKeys() { return this.api("/api/client/account/api-keys"); } async createAPIKey(description, allowedIPs) { return this.api("/api/client/account/api-keys", { description, allowed_ips: allowedIPs, }, "POST"); } async deleteAPIKey(identifier) { await this.api(`/api/client/account/api-keys/${identifier}`, {}, "DELETE"); } // Server Management async listServers(options) { const query = new URLSearchParams(); if (options?.includeEgg) query.append('include', 'egg'); if (options?.includeSubusers) query.append('include', 'subusers'); const queryString = query.toString() ? `?${query.toString()}` : ''; return this.api(`/api/client${queryString}`); } async getServerDetails(serverId) { return this.api(`/api/client/servers/${serverId}`); } async renameServer(serverId, newName) { await this.api(`/api/client/servers/${serverId}/settings/rename`, { name: newName }, "POST"); } async reinstallServer(serverId) { await this.api(`/api/client/servers/${serverId}/settings/reinstall`, {}, "POST"); } // Database Management async listDatabases(serverId) { return this.api(`/api/client/servers/${serverId}/databases`); } async createDatabase(serverId, database, remote) { return this.api(`/api/client/servers/${serverId}/databases`, { database, remote }, "POST"); } async generateDatabasePassword(serverId, databaseId) { return this.api(`/api/client/servers/${serverId}/databases/${databaseId}/rotate-password`, {}, "POST"); } async deleteDatabase(serverId, databaseId) { await this.api(`/api/client/servers/${serverId}/databases/${databaseId}`, {}, "DELETE"); } // File Management async listFiles(serverId, directory) { const query = directory ? `?directory=${encodeURIComponent(directory)}` : ""; return this.api(`/api/client/servers/${serverId}/files/list${query}`); } async readFileContents(serverId, filePath) { const encodedPath = encodeURIComponent(filePath); return this.api(`/api/client/servers/${serverId}/files/contents?file=${encodedPath}`); } async writeFile(serverId, filePath, content) { await this.api(`/api/client/servers/${serverId}/files/write?file=${encodeURIComponent(filePath)}`, content, "POST"); } async renameFile(serverId, root, from, to) { await this.api(`/api/client/servers/${serverId}/files/rename`, { root, files: [{ from, to }], }, "PUT"); } async copyFile(serverId, filePath) { await this.api(`/api/client/servers/${serverId}/files/copy`, { location: filePath }, "POST"); } async compressFiles(serverId, root, files) { await this.api(`/api/client/servers/${serverId}/files/compress`, { root, files }, "POST"); } async decompressFile(serverId, root, file) { await this.api(`/api/client/servers/${serverId}/files/decompress`, { root, file }, "POST"); } async deleteFiles(serverId, root, files) { await this.api(`/api/client/servers/${serverId}/files/delete`, { root, files }, "POST"); } async createFolder(serverId, root, name) { await this.api(`/api/client/servers/${serverId}/files/create-folder`, { root, name }, "POST"); } async generateUploadURL(serverId) { return this.api(`/api/client/servers/${serverId}/files/upload`); } async downloadFile(serverId, filePath) { const encodedPath = encodeURIComponent(filePath); return this.api(`/api/client/servers/${serverId}/files/download?file=${encodedPath}`); } // Schedule Management async listSchedules(serverId) { return this.api(`/api/client/servers/${serverId}/schedules`); } async createSchedule(serverId, name, cron, isActive = true) { await this.api(`/api/client/servers/${serverId}/schedules`, { name, minute: cron.minute, hour: cron.hour, day_of_month: cron.dayOfMonth, day_of_week: cron.dayOfWeek, is_active: isActive, }, "POST"); } async getScheduleDetails(serverId, scheduleId) { return this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}`); } async updateSchedule(serverId, scheduleId, name, cron, isActive) { const body = { name, minute: cron.minute, hour: cron.hour, day_of_month: cron.dayOfMonth, day_of_week: cron.dayOfWeek, }; if (typeof isActive !== "undefined") { body.is_active = isActive; } await this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}`, body, "POST"); } async deleteSchedule(serverId, scheduleId) { await this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}`, {}, "DELETE"); } // Task Management async createTask(serverId, scheduleId, action, payload, timeOffset) { await this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}/tasks`, { action, payload, time_offset: timeOffset }, "POST"); } async updateTask(serverId, scheduleId, taskId, action, payload, timeOffset) { await this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}/tasks/${taskId}`, { action, payload, time_offset: timeOffset }, "POST"); } async deleteTask(serverId, scheduleId, taskId) { await this.api(`/api/client/servers/${serverId}/schedules/${scheduleId}/tasks/${taskId}`, {}, "DELETE"); } // Network/Allocation Management async listAllocations(serverId) { return this.api(`/api/client/servers/${serverId}/network/allocations`); } async assignAllocation(serverId) { return this.api(`/api/client/servers/${serverId}/network/allocations`, {}, "POST"); } async setAllocationNote(serverId, allocationId, notes) { await this.api(`/api/client/servers/${serverId}/network/allocations/${allocationId}`, { notes }, "POST"); } async setPrimaryAllocation(serverId, allocationId) { await this.api(`/api/client/servers/${serverId}/network/allocations/${allocationId}/primary`, {}, "POST"); } async unassignAllocation(serverId, allocationId) { await this.api(`/api/client/servers/${serverId}/network/allocations/${allocationId}`, {}, "DELETE"); } // User Management async listUsers(serverId) { return this.api(`/api/client/servers/${serverId}/users`); } async createUser(serverId, email, permissions) { await this.api(`/api/client/servers/${serverId}/users`, { email, permissions }, "POST"); } async getSubUserDetails(serverId, subuserUuid) { return this.api(`/api/client/servers/${serverId}/users/${subuserUuid}`); } async updateUser(serverId, subuserUuid, permissions) { await this.api(`/api/client/servers/${serverId}/users/${subuserUuid}`, { permissions }, "POST"); } async deleteUser(serverId, subuserUuid) { await this.api(`/api/client/servers/${serverId}/users/${subuserUuid}`, {}, "DELETE"); } // Backup Management async listBackups(serverId) { return this.api(`/api/client/servers/${serverId}/backups`); } async createBackup(serverId, name, ignored) { const body = {}; if (name) body.name = name; if (ignored) body.ignored = ignored; await this.api(`/api/client/servers/${serverId}/backups`, body, "POST"); } async getBackupDetails(serverId, backupUuid) { return this.api(`/api/client/servers/${serverId}/backups/${backupUuid}`); } async getBackupDownloadLink(serverId, backupUuid) { return this.api(`/api/client/servers/${serverId}/backups/${backupUuid}/download`); } async deleteBackup(serverId, backupUuid) { await this.api(`/api/client/servers/${serverId}/backups/${backupUuid}`, {}, "DELETE"); } // Startup Variables async listStartupVariables(serverId) { return this.api(`/api/client/servers/${serverId}/startup`); } async updateStartupVariable(serverId, key, value) { await this.api(`/api/client/servers/${serverId}/startup/variable`, { key, value }, "PUT"); } } /* interface WebSocketToken { object: "websocket_token"; data: { token: string; socket: string; }; } export class WebsocketApi { private clientApi: ClientApi; private ws?: typeof import("ws"); constructor(clientApi: ClientApi) { this.clientApi = clientApi; } private async loadWs() { if (!this.ws) { try { const mod = await import("ws"); // "ws" has both CommonJS and ESM export shapes this.ws = (mod.WebSocket || (mod as any).default) as typeof import("ws"); } catch { throw new Error( "Missing dependency: 'ws'. Please install it to use WebSocket features." ); } } return this.ws; } async getToken(serverUUID: string): Promise<WebSocketToken> { return this.clientApi.api( `/api/client/servers/${serverUUID}/websocket` ) as Promise<WebSocketToken>; } async connect(serverUUID: string) { const wsLib = await this.loadWs(); const {data} = await this.getToken(serverUUID); // Create WebSocket connection const socket = new wsLib(data.socket, { headers: { Authorization: `Bearer ${data.token}`, }, }); socket.onopen = () => { console.log("WebSocket connection established"); // Authenticate with the server socket.send( JSON.stringify({ event: "auth", args: [data.token], }) ); }; return socket; } }*/ //# sourceMappingURL=index.js.map