UNPKG

@pelican.ts/sdk

Version:

Pelican panel SDK for TypeScript

1,937 lines (1,904 loc) 58.9 kB
// src/api/client/account.ts import z from "zod"; var Account = class { r; constructor(requester) { this.r = requester; } info = async () => { const { data } = await this.r.get("/account"); return data.attributes; }; updateEmail = async (newEmail, password) => { newEmail = z.email().parse(newEmail); await this.r.put("/account/email", { email: newEmail, password }); }; updatePassword = async (newPassword) => { newPassword = z.string().min(8).parse(newPassword); await this.r.put("/account/password", { password: newPassword, password_confirmation: newPassword }); }; apiKeys = { list: async () => { const { data } = await this.r.get("/account/api-keys"); return data.data.map((k) => k.attributes); }, create: async (description, allowed_ips) => { allowed_ips = z.array(z.ipv4()).optional().parse(allowed_ips); const { data } = await this.r.post("/account/api-keys", { description, allowed_ips }); return { ...data.attributes, secret_token: data.meta.secret_token }; }, delete: async (identifier) => { await this.r.delete(`/account/api-keys/${identifier}`); } }; sshKeys = { list: async () => { const { data } = await this.r.get("/account/ssh-keys"); return data.data.map((k) => k.attributes); }, create: async (name, public_key) => { const { data } = await this.r.post("/account/ssh-keys", { name, public_key }); return data.attributes; }, delete: async (fingerprint) => { await this.r.delete(`/account/ssh-keys/${fingerprint}`); } }; }; // src/api/client/client.ts import z5 from "zod"; // src/api/client/server_databases.ts import z2 from "zod"; var ServerDatabases = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async (include, page = 1) => { z2.number().positive().parse(page); const { data } = await this.r.get(`/servers/${this.id}/databases`, { params: { include: include?.join(","), page } }); return data.data.map((d) => d.attributes); }; create = async (database, remote) => { const { data } = await this.r.post(`/servers/${this.id}/databases`, { database, remote }); return data.attributes; }; rotatePassword = async (database_id) => { const { data } = await this.r.post(`/servers/${this.id}/databases/${database_id}/rotate-password`); return data.attributes; }; delete = async (database_id) => { await this.r.delete(`/servers/${this.id}/databases/${database_id}`); }; }; // src/api/client/server_files.ts import axios from "axios"; var ServerFiles = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async (path2) => { const { data } = await this.r.get(`/servers/${this.id}/files/list`, { params: { directory: path2 } }); return data.data.map((r) => r.attributes); }; /** * Return the contents of a file. To read binary file (non-editable) use {@link download} instead */ contents = async (path2) => { const { data } = await this.r.get( `/servers/${this.id}/files/contents`, { params: { file: path2 } } ); return data; }; downloadGetUrl = async (path2) => { const { data } = await this.r.get(`/servers/${this.id}/files/download`, { params: { file: path2 } }); return data.attributes.url; }; download = async (path2) => { const url = await this.downloadGetUrl(path2); const { data } = await axios.get(url, { responseType: "arraybuffer" }); return data; }; rename = async (root = "/", files) => { await this.r.put(`/servers/${this.id}/files/rename`, { root, files }); }; copy = async (location) => { await this.r.post(`/servers/${this.id}/files/copy`, { location }); }; write = async (path2, content) => { await this.r.post(`/servers/${this.id}/files/write`, content, { params: { file: path2 } }); }; compress = async (root = "/", files, archive_name, extension) => { const { data } = await this.r.post(`/servers/${this.id}/files/compress`, { root, files, archive_name, extension }); return data.attributes; }; decompress = async (root = "/", file) => { await this.r.post(`/servers/${this.id}/files/decompress`, { root, file }); }; delete = async (root = "/", files) => { await this.r.post(`/servers/${this.id}/files/delete`, { root, files }); }; createFolder = async (root = "/", name) => { await this.r.post(`/servers/${this.id}/files/create-folder`, { root, name }); }; chmod = async (root = "/", files) => { await this.r.post(`/servers/${this.id}/files/chmod`, { root, files }); }; pullFromRemote = async (url, directory, filename, use_header = false, foreground = false) => { await this.r.post(`/servers/${this.id}/files/pull`, { url, directory, filename, use_header, foreground }); }; uploadGetUrl = async () => { const { data } = await this.r.get(`/servers/${this.id}/files/upload`); return data.attributes.url; }; upload = async (file, root = "/") => { const url = await this.uploadGetUrl(); await axios.post( url, { files: file }, { headers: { "Content-Type": "multipart/form-data" }, params: { directory: root } } ); }; }; // src/api/client/server_schedules.ts var ServerSchedules = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async () => { const { data } = await this.r.get(`/servers/${this.id}/schedules`); return data.data.map((d) => d.attributes); }; create = async (params) => { const { data } = await this.r.post(`/servers/${this.id}/schedules`, params); return data.attributes; }; control = (sched_id) => new ScheduleControl(this.r, this.id, sched_id); }; var ScheduleControl = class { r; id; sched_id; constructor(requester, id, sched_id) { this.r = requester; this.id = id; this.sched_id = sched_id; } info = async () => { const { data } = await this.r.get(`/servers/${this.id}/schedules/${this.sched_id}`); return data.attributes; }; update = async (params) => { const { data } = await this.r.post(`/servers/${this.id}/schedules/${this.sched_id}`, params); return data.attributes; }; delete = async () => { await this.r.delete(`/servers/${this.id}/schedules/${this.sched_id}`); }; execute = async () => { await this.r.post( `/servers/${this.id}/schedules/${this.sched_id}/execute` ); }; tasks = { create: async (opts) => { const { data } = await this.r.post(`/servers/${this.id}/schedules/${this.sched_id}/tasks`, opts); return data.attributes; }, update: async (task_id, opts) => { const { data } = await this.r.post( `/servers/${this.id}/schedules/${this.sched_id}/tasks/${task_id}`, opts ); return data.attributes; }, delete: async (task_id) => { await this.r.delete( `/servers/${this.id}/schedules/${this.sched_id}/tasks/${task_id}` ); } }; }; // src/api/client/server_allocations.ts var ServerAllocations = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async () => { const { data } = await this.r.get(`/servers/${this.id}/network/allocations`); return data.data.map((r) => r.attributes); }; autoAssign = async () => { const { data } = await this.r.post(`/servers/${this.id}/network/allocations`); return data.attributes; }; setNotes = async (alloc_id, notes) => { const { data } = await this.r.post(`/servers/${this.id}/network/allocations/${alloc_id}`, { notes }); return data.attributes; }; setPrimary = async (alloc_id) => { const { data } = await this.r.post(`/servers/${this.id}/network/allocations/${alloc_id}/primary`); return data.attributes; }; unassign = async (alloc_id) => { await this.r.delete( `/servers/${this.id}/network/allocations/${alloc_id}` ); }; }; // src/api/client/server_users.ts var ServerUsers = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async () => { const { data } = await this.r.get(`/servers/${this.id}/users`); return data.data.map((d) => d.attributes); }; create = async (email, permissions) => { const { data } = await this.r.post(`/servers/${this.id}/users`, { email, permissions }); return data.attributes; }; info = async (user_uuid) => { const { data } = await this.r.get( `/servers/${this.id}/users/${user_uuid}` ); return data.attributes; }; update = async (user_uuid, permissions) => { const { data } = await this.r.put( `/servers/${this.id}/users/${user_uuid}`, { permissions } ); return data.attributes; }; delete = async (user_uuid) => { await this.r.delete(`/servers/${this.id}/users/${user_uuid}`); }; }; // src/api/client/server_backups.ts import axios2 from "axios"; import z3 from "zod"; var ServerBackups = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async (page = 1) => { z3.number().positive().parse(page); const { data } = await this.r.get(`/servers/${this.id}/backups`, { params: { page } }); return data.data.map((d) => d.attributes); }; create = async (args) => { args.name = z3.string().max(255).optional().parse(args.name); const { data } = await this.r.post(`/servers/${this.id}/backups`, { name: args.name, is_locked: args.is_locked, ignored_files: args.ignored_files.join("\n") }); return data.attributes; }; info = async (backup_uuid) => { const { data } = await this.r.get(`/servers/${this.id}/backups/${backup_uuid}`); return data.attributes; }; downloadGetUrl = async (backup_uuid) => { const { data } = await this.r.get(`/servers/${this.id}/backups/${backup_uuid}/download`); return data.attributes.url; }; download = async (backup_uuid) => { const url = await this.downloadGetUrl(backup_uuid); const { data } = await axios2.get(url, { responseType: "arraybuffer" }); return data; }; delete = async (backup_uuid) => { await this.r.delete(`/servers/${this.id}/backups/${backup_uuid}`); }; rename = async (backup_uuid, name) => { await this.r.put(`/servers/${this.id}/backups/${backup_uuid}/rename`, { name }); }; toggleLock = async (backup_uuid) => { await this.r.post(`/servers/${this.id}/backups/${backup_uuid}/lock`); }; restore = async (backup_uuid, truncate) => { await this.r.post( `/servers/${this.id}/backups/${backup_uuid}/restore`, { truncate } ); }; }; // src/api/client/server_startup.ts var ServerStartup = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } list = async () => { const { data } = await this.r.get(`/servers/${this.id}/startup`); return { object: "list", meta: data.meta, data: data.data.map((d) => d.attributes) }; }; set = async (key, value) => { const { data } = await this.r.put(`/servers/${this.id}/startup/variable`, { key, value }); return data.attributes; }; }; // src/api/client/server_settings.ts import z4 from "zod"; var ServerSettings = class { r; id; constructor(requester, id) { this.r = requester; this.id = id; } rename = async (name) => { name = z4.string().max(255).parse(name); await this.r.post(`/servers/${this.id}/settings/rename`, { name }); }; updateDescription = async (description) => { await this.r.post(`/servers/${this.id}/settings/description`, { description }); }; reinstall = async () => { await this.r.post(`/servers/${this.id}/settings/reinstall`); }; changeDockerImage = async (image) => { await this.r.put(`/servers/${this.id}/settings/docker-image`, { docker_image: image }); }; }; // src/api/client/server_websocket.ts import { EventEmitter } from "events"; import WebSocket from "isomorphic-ws"; import stripColor from "strip-color"; var isBrowser = typeof window !== "undefined"; var RECONNECT_ERRORS = /* @__PURE__ */ new Set([ "jwt: exp claim is invalid", "jwt: created too far in past (denylist)" ]); var FALLBACK_LOG_MESSAGE = "No logs - is the server online?"; var ServerWebsocket = class { r; serverId; socket; currentToken; bus = new EventEmitter(); debugLogging = false; stripColors; detachMessageListener; constructor(requester, id, stripColors = false) { this.r = requester; this.serverId = id; this.stripColors = stripColors; } on(event, listener) { const handler = listener; this.bus.on(event, handler); return () => { this.bus.removeListener(event, handler); }; } deregister(event, listener) { const handler = listener; this.bus.removeListener(event, handler); } emit(event, ...args) { if (args.length === 0) { this.bus.emit(event); } else { this.bus.emit(event, args[0]); } } async connect(resumable, debugLogging) { this.debugLogging = debugLogging ?? false; if (this.socket) { return; } const socketUrl = await this.refreshCredentials(); this.socket = isBrowser ? new WebSocket(socketUrl) : new WebSocket(socketUrl, void 0, { origin: new URL(socketUrl).origin }); await new Promise((resolve, reject) => { const socket = this.socket; if (!socket) { reject(new Error("Failed to create socket connection")); return; } socket.onopen = async () => { try { await this.authenticate(); this.attachMessageListener(); socket.onopen = null; socket.onerror = null; resolve(); } catch (error) { socket.onopen = null; socket.onerror = null; reject( error instanceof Error ? error : new Error("Websocket authentication failed") ); } }; socket.onerror = (event) => { socket.onopen = null; socket.onerror = null; reject( event instanceof Error ? event : new Error("Websocket connection error") ); }; }); if (resumable) { this.makeResumable(true); } } onSocketDisconnect(handler) { if (!this.socket) { console.error(new Error("No socket connection")); return; } this.socket.onclose = handler; } onSocketError(handler) { if (!this.socket) { console.error(new Error("No socket connection")); return; } this.socket.onerror = handler; } makeResumable(disconnectsToo) { const scheduleReconnect = () => { setTimeout(() => { const previous = this.socket; this.detachMessageListener?.(); this.detachMessageListener = void 0; this.socket = void 0; previous?.close(); void this.connect(true, this.debugLogging); }, 1e3); }; this.onSocketError(() => scheduleReconnect()); if (disconnectsToo) { this.onSocketDisconnect(() => scheduleReconnect()); } } attachMessageListener() { if (!this.socket) { throw new Error("No socket connection"); } this.detachMessageListener?.(); const handler = (event) => { void this.handleIncomingMessage(event); }; if (typeof this.socket.addEventListener === "function") { this.socket.addEventListener( "message", handler ); this.detachMessageListener = () => { this.socket?.removeEventListener?.( "message", handler ); }; } else { const fallback = (data) => handler({ data }); const socket = this.socket; socket.on?.("message", fallback); this.detachMessageListener = () => { const target = this.socket; if (!target) { return; } if (typeof target.off === "function") { target.off("message", fallback); } else if (typeof target.removeListener === "function") { target.removeListener("message", fallback); } }; } } async handleIncomingMessage(event) { const message = this.parseMessage(event); if (!message) { return; } try { await this.dispatchMessage(message); } catch (error) { if (this.debugLogging) { console.error("Error while handling websocket message", error); } } } parseMessage(event) { const payload = this.normalisePayload(event); if (!payload) { return null; } try { return JSON.parse(payload); } catch (error) { if (this.debugLogging) { console.warn("Failed to parse websocket payload", error); } return null; } } normalisePayload(event) { if (typeof event === "string") { return event; } if (typeof event === "object" && event !== null && "data" in event) { return this.normalisePayload(event.data); } if (typeof Buffer !== "undefined" && Buffer.isBuffer(event)) { return event.toString("utf8"); } if (typeof ArrayBuffer !== "undefined" && event instanceof ArrayBuffer) { if (typeof TextDecoder !== "undefined") { return new TextDecoder().decode(new Uint8Array(event)); } if (typeof Buffer !== "undefined") { return Buffer.from(event).toString("utf8"); } } return null; } async dispatchMessage(message) { switch (message.event) { case "auth success" /* AUTH_SUCCESS */: { if (this.debugLogging) { console.debug("Auth success"); } this.emit("auth success" /* AUTH_SUCCESS */); break; } case "status" /* STATUS */: { if (this.debugLogging) { console.debug("Received status event", message.args[0]); } this.emit("status" /* STATUS */, message.args[0]); break; } case "console output" /* CONSOLE_OUTPUT */: { let output = message.args[0]; if (this.stripColors) { output = stripColor(output); } if (this.debugLogging) { console.debug("Received console output", output); } this.emit("console output" /* CONSOLE_OUTPUT */, output); break; } case "stats" /* STATS */: { try { const payload = JSON.parse(message.args[0]); this.emit("stats" /* STATS */, payload); } catch (error) { if (this.debugLogging) { console.warn("Failed to parse stats payload", error); } } break; } case "daemon error" /* DAEMON_ERROR */: { this.emit("daemon error" /* DAEMON_ERROR */); break; } case "backup completed" /* BACKUP_COMPLETED */: { try { const payload = JSON.parse( message.args[0] ); this.emit("backup completed" /* BACKUP_COMPLETED */, payload); } catch (error) { if (this.debugLogging) { console.warn("Failed to parse backup payload", error); } } break; } case "daemon message" /* DAEMON_MESSAGE */: { let output = message.args[0]; if (this.stripColors) { output = stripColor(output); } this.emit("daemon message" /* DAEMON_MESSAGE */, output); break; } case "install output" /* INSTALL_OUTPUT */: { let output = message.args[0]; if (this.stripColors) { output = stripColor(output); } this.emit("install output" /* INSTALL_OUTPUT */, output); break; } case "backup restore completed" /* BACKUP_RESTORE_COMPLETED */: { this.emit("backup restore completed" /* BACKUP_RESTORE_COMPLETED */); break; } case "install completed" /* INSTALL_COMPLETED */: { this.emit("install completed" /* INSTALL_COMPLETED */); break; } case "install started" /* INSTALL_STARTED */: { this.emit("install started" /* INSTALL_STARTED */); break; } case "transfer logs" /* TRANSFER_LOGS */: { this.emit("transfer logs" /* TRANSFER_LOGS */, message.args[0]); break; } case "transfer status" /* TRANSFER_STATUS */: { this.emit("transfer status" /* TRANSFER_STATUS */, message.args[0]); break; } case "token expiring" /* TOKEN_EXPIRING */: { this.emit("token expiring" /* TOKEN_EXPIRING */); if (this.debugLogging) { console.warn("Token expiring, renewing..."); } await this.refreshCredentials(); await this.authenticate(); break; } case "token expired" /* TOKEN_EXPIRED */: { this.emit("token expired" /* TOKEN_EXPIRED */); throw new Error("Token expired"); } case "jwt error" /* JWT_ERROR */: { const reason = message.args[0]; if (RECONNECT_ERRORS.has(reason)) { this.emit("token expiring" /* TOKEN_EXPIRING */); if (this.debugLogging) { console.warn("Token expiring (JWT error), renewing..."); } await this.refreshCredentials(); await this.authenticate(); } else { this.emit("jwt error" /* JWT_ERROR */, reason); throw new Error("Token expired"); } break; } default: { if (this.debugLogging) { console.warn("Unknown websocket event", message); } break; } } } async refreshCredentials() { const { data } = await this.r.get( `/servers/${this.serverId}/websocket` ); this.currentToken = data.data.token; return data.data.socket; } async authenticate() { if (!this.socket) { throw new Error("No socket connection"); } if (!this.currentToken) { throw new Error("Missing websocket token"); } this.socket.send( JSON.stringify({ event: "auth", args: [this.currentToken] }) ); } disconnect() { this.detachMessageListener?.(); this.detachMessageListener = void 0; if (this.socket) { this.socket.close(); this.socket = void 0; } } requestStats() { this.send("send stats", [null]); } requestLogs() { this.send("send logs", [null]); } send(event, args) { if (!this.socket) { if (this.debugLogging) { console.warn( `Attempted to send "${event}" without an active websocket connection` ); } return; } this.socket.send(JSON.stringify({ event, args })); } getStats() { return new Promise((resolve, reject) => { if (!this.socket) { reject(new Error("No socket connection")); return; } let off; const timeout = setTimeout(() => { off?.(); reject(new Error("Timed out waiting for stats")); }, 5e3); off = this.on("stats" /* STATS */, (payload) => { clearTimeout(timeout); off?.(); resolve(payload); }); this.requestStats(); }); } getLogs() { return new Promise((resolve, reject) => { if (!this.socket) { reject(new Error("No socket connection")); return; } const lines = []; let off; let initialTimeout; let idleTimeout; const finalize = (payload) => { off?.(); if (initialTimeout) { clearTimeout(initialTimeout); } if (idleTimeout) { clearTimeout(idleTimeout); } resolve(payload); }; initialTimeout = setTimeout(() => { finalize(lines.length > 0 ? lines : [FALLBACK_LOG_MESSAGE]); }, 5e3); off = this.on("console output" /* CONSOLE_OUTPUT */, (line) => { lines.push(line); if (initialTimeout) { clearTimeout(initialTimeout); initialTimeout = void 0; } if (idleTimeout) { clearTimeout(idleTimeout); } idleTimeout = setTimeout(() => { finalize(lines); }, 1e3); }); this.requestLogs(); }); } sendPoweraction(action) { this.send("set state", [action]); } sendCommand(cmd) { this.send("send command", [cmd]); } }; // src/api/client/server_activity.ts var ServerActivity = class { r; id; constructor(r, id) { this.r = r; this.id = id; } list = async (page = 1, per_page = 25) => { const { data } = await this.r.get(`/server/${this.id}/activity`, { params: { page, per_page } }); return data.data.map((log) => log.attributes); }; }; // src/api/client/server.ts var ServerClient = class { r; id; activity; databases; files; schedules; allocations; users; backups; startup; variables; settings; constructor(requester, id) { this.r = requester; this.id = id; this.activity = new ServerActivity(requester, id); this.databases = new ServerDatabases(requester, id); this.files = new ServerFiles(requester, id); this.schedules = new ServerSchedules(requester, id); this.allocations = new ServerAllocations(requester, id); this.users = new ServerUsers(requester, id); this.backups = new ServerBackups(requester, id); this.startup = new ServerStartup(requester, id); this.variables = this.startup; this.settings = new ServerSettings(requester, id); } info = async (include) => { const { data } = await this.r.get( `/servers/${this.id}`, { params: { include: include?.join(",") } } ); return data.attributes; }; websocket = (stripColors = false) => { return new ServerWebsocket(this.r, this.id, stripColors); }; resources = async () => { const { data } = await this.r.get( `/servers/${this.id}/resources` ); return data.attributes; }; command = async (command) => { await this.r.post(`/servers/${this.id}/command`, { command }); }; power = async (signal) => { await this.r.post(`/servers/${this.id}/power`, { signal }); }; }; // src/api/client/client.ts var Client = class { account; r; constructor(requester) { this.r = requester; this.account = new Account(requester); } get $r() { return this.r; } listPermissions = async () => { const { data } = await this.r.get("/permissions"); return data.attributes.permissions; }; listServers = async (type = "accessible", page = 1, per_page = 50, include) => { z5.number().positive().parse(page); const { data } = await this.r.get("/", { params: { type, page, include: include?.join(",") } }); return data.data.map((s) => s.attributes); }; server = (uuid) => new ServerClient(this.r, uuid); }; // src/api/application/users.ts import z7 from "zod"; // src/api/common/types/enums.ts import z6 from "zod"; var languagesSchema = z6.enum([ "af", "ak", "am", "ar", "as", "az", "be", "bg", "bm", "bn", "bo", "br", "bs", "ca", "ce", "cs", "cv", "cy", "da", "de", "dz", "ee", "el", "en", "eo", "es", "et", "eu", "fa", "ff", "fi", "fo", "fr", "fy", "ga", "gd", "gl", "gu", "gv", "ha", "he", "hi", "hr", "hu", "hy", "ia", "id", "ig", "ii", "is", "it", "ja", "jv", "ka", "ki", "kk", "kl", "km", "kn", "ko", "ks", "ku", "kw", "ky", "lb", "lg", "ln", "lo", "lt", "lu", "lv", "mg", "mi", "mk", "ml", "mn", "mr", "ms", "mt", "my", "nb", "nd", "ne", "nl", "nn", "no", "om", "or", "os", "pa", "pl", "ps", "pt", "qu", "rm", "rn", "ro", "ru", "rw", "sa", "sc", "sd", "se", "sg", "si", "sk", "sl", "sn", "so", "sq", "sr", "su", "sv", "sw", "ta", "te", "tg", "th", "ti", "tk", "to", "tr", "tt", "ug", "uk", "ur", "uz", "vi", "wo", "xh", "yi", "yo", "zh", "zu" ]); var timezonesSchema = z6.enum([ "Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa", "Africa/Algiers", "Africa/Asmara", "Africa/Bamako", "Africa/Bangui", "Africa/Banjul", "Africa/Bissau", "Africa/Blantyre", "Africa/Brazzaville", "Africa/Bujumbura", "Africa/Cairo", "Africa/Casablanca", "Africa/Ceuta", "Africa/Conakry", "Africa/Dakar", "Africa/Dar_es_Salaam", "Africa/Djibouti", "Africa/Douala", "Africa/El_Aaiun", "Africa/Freetown", "Africa/Gaborone", "Africa/Harare", "Africa/Johannesburg", "Africa/Juba", "Africa/Kampala", "Africa/Khartoum", "Africa/Kigali", "Africa/Kinshasa", "Africa/Lagos", "Africa/Libreville", "Africa/Lome", "Africa/Luanda", "Africa/Lubumbashi", "Africa/Lusaka", "Africa/Malabo", "Africa/Maputo", "Africa/Maseru", "Africa/Mbabane", "Africa/Mogadishu", "Africa/Monrovia", "Africa/Nairobi", "Africa/Ndjamena", "Africa/Niamey", "Africa/Nouakchott", "Africa/Ouagadougou", "Africa/Porto-Novo", "Africa/Sao_Tome", "Africa/Tripoli", "Africa/Tunis", "Africa/Windhoek", "America/Adak", "America/Anchorage", "America/Anguilla", "America/Antigua", "America/Araguaina", "America/Argentina/Buenos_Aires", "America/Argentina/Catamarca", "America/Argentina/Cordoba", "America/Argentina/Jujuy", "America/Argentina/La_Rioja", "America/Argentina/Mendoza", "America/Argentina/Rio_Gallegos", "America/Argentina/Salta", "America/Argentina/San_Juan", "America/Argentina/San_Luis", "America/Argentina/Tucuman", "America/Argentina/Ushuaia", "America/Aruba", "America/Asuncion", "America/Atikokan", "America/Bahia", "America/Bahia_Banderas", "America/Barbados", "America/Belem", "America/Belize", "America/Blanc-Sablon", "America/Boa_Vista", "America/Bogota", "America/Boise", "America/Cambridge_Bay", "America/Campo_Grande", "America/Cancun", "America/Caracas", "America/Cayenne", "America/Cayman", "America/Chicago", "America/Chihuahua", "America/Ciudad_Juarez", "America/Costa_Rica", "America/Coyhaique", "America/Creston", "America/Cuiaba", "America/Curacao", "America/Danmarkshavn", "America/Dawson", "America/Dawson_Creek", "America/Denver", "America/Detroit", "America/Dominica", "America/Edmonton", "America/Eirunepe", "America/El_Salvador", "America/Fort_Nelson", "America/Fortaleza", "America/Glace_Bay", "America/Goose_Bay", "America/Grand_Turk", "America/Grenada", "America/Guadeloupe", "America/Guatemala", "America/Guayaquil", "America/Guyana", "America/Halifax", "America/Havana", "America/Hermosillo", "America/Indiana/Indianapolis", "America/Indiana/Knox", "America/Indiana/Marengo", "America/Indiana/Petersburg", "America/Indiana/Tell_City", "America/Indiana/Vevay", "America/Indiana/Vincennes", "America/Indiana/Winamac", "America/Inuvik", "America/Iqaluit", "America/Jamaica", "America/Juneau", "America/Kentucky/Louisville", "America/Kentucky/Monticello", "America/Kralendijk", "America/La_Paz", "America/Lima", "America/Los_Angeles", "America/Lower_Princes", "America/Maceio", "America/Managua", "America/Manaus", "America/Marigot", "America/Martinique", "America/Matamoros", "America/Mazatlan", "America/Menominee", "America/Merida", "America/Metlakatla", "America/Mexico_City", "America/Miquelon", "America/Moncton", "America/Monterrey", "America/Montevideo", "America/Montserrat", "America/Nassau", "America/New_York", "America/Nome", "America/Noronha", "America/North_Dakota/Beulah", "America/North_Dakota/Center", "America/North_Dakota/New_Salem", "America/Nuuk", "America/Ojinaga", "America/Panama", "America/Paramaribo", "America/Phoenix", "America/Port-au-Prince", "America/Port_of_Spain", "America/Porto_Velho", "America/Puerto_Rico", "America/Punta_Arenas", "America/Rankin_Inlet", "America/Recife", "America/Regina", "America/Resolute", "America/Rio_Branco", "America/Santarem", "America/Santiago", "America/Santo_Domingo", "America/Sao_Paulo", "America/Scoresbysund", "America/Sitka", "America/St_Barthelemy", "America/St_Johns", "America/St_Kitts", "America/St_Lucia", "America/St_Thomas", "America/St_Vincent", "America/Swift_Current", "America/Tegucigalpa", "America/Thule", "America/Tijuana", "America/Toronto", "America/Tortola", "America/Vancouver", "America/Whitehorse", "America/Winnipeg", "America/Yakutat", "Antarctica/Casey", "Antarctica/Davis", "Antarctica/DumontDUrville", "Antarctica/Macquarie", "Antarctica/Mawson", "Antarctica/McMurdo", "Antarctica/Palmer", "Antarctica/Rothera", "Antarctica/Syowa", "Antarctica/Troll", "Antarctica/Vostok", "Arctic/Longyearbyen", "Asia/Aden", "Asia/Almaty", "Asia/Amman", "Asia/Anadyr", "Asia/Aqtau", "Asia/Aqtobe", "Asia/Ashgabat", "Asia/Atyrau", "Asia/Baghdad", "Asia/Bahrain", "Asia/Baku", "Asia/Bangkok", "Asia/Barnaul", "Asia/Beirut", "Asia/Bishkek", "Asia/Brunei", "Asia/Chita", "Asia/Colombo", "Asia/Damascus", "Asia/Dhaka", "Asia/Dili", "Asia/Dubai", "Asia/Dushanbe", "Asia/Famagusta", "Asia/Gaza", "Asia/Hebron", "Asia/Ho_Chi_Minh", "Asia/Hong_Kong", "Asia/Hovd", "Asia/Irkutsk", "Asia/Jakarta", "Asia/Jayapura", "Asia/Jerusalem", "Asia/Kabul", "Asia/Kamchatka", "Asia/Karachi", "Asia/Kathmandu", "Asia/Khandyga", "Asia/Kolkata", "Asia/Krasnoyarsk", "Asia/Kuala_Lumpur", "Asia/Kuching", "Asia/Kuwait", "Asia/Macau", "Asia/Magadan", "Asia/Makassar", "Asia/Manila", "Asia/Muscat", "Asia/Nicosia", "Asia/Novokuznetsk", "Asia/Novosibirsk", "Asia/Omsk", "Asia/Oral", "Asia/Phnom_Penh", "Asia/Pontianak", "Asia/Pyongyang", "Asia/Qatar", "Asia/Qostanay", "Asia/Qyzylorda", "Asia/Riyadh", "Asia/Sakhalin", "Asia/Samarkand", "Asia/Seoul", "Asia/Shanghai", "Asia/Singapore", "Asia/Srednekolymsk", "Asia/Taipei", "Asia/Tashkent", "Asia/Tbilisi", "Asia/Tehran", "Asia/Thimphu", "Asia/Tokyo", "Asia/Tomsk", "Asia/Ulaanbaatar", "Asia/Urumqi", "Asia/Ust-Nera", "Asia/Vientiane", "Asia/Vladivostok", "Asia/Yakutsk", "Asia/Yangon", "Asia/Yekaterinburg", "Asia/Yerevan", "Atlantic/Azores", "Atlantic/Bermuda", "Atlantic/Canary", "Atlantic/Cape_Verde", "Atlantic/Faroe", "Atlantic/Madeira", "Atlantic/Reykjavik", "Atlantic/South_Georgia", "Atlantic/St_Helena", "Atlantic/Stanley", "Australia/Adelaide", "Australia/Brisbane", "Australia/Broken_Hill", "Australia/Darwin", "Australia/Eucla", "Australia/Hobart", "Australia/Lindeman", "Australia/Lord_Howe", "Australia/Melbourne", "Australia/Perth", "Australia/Sydney", "Europe/Amsterdam", "Europe/Andorra", "Europe/Astrakhan", "Europe/Athens", "Europe/Belgrade", "Europe/Berlin", "Europe/Bratislava", "Europe/Brussels", "Europe/Bucharest", "Europe/Budapest", "Europe/Busingen", "Europe/Chisinau", "Europe/Copenhagen", "Europe/Dublin", "Europe/Gibraltar", "Europe/Guernsey", "Europe/Helsinki", "Europe/Isle_of_Man", "Europe/Istanbul", "Europe/Jersey", "Europe/Kaliningrad", "Europe/Kirov", "Europe/Kyiv", "Europe/Lisbon", "Europe/Ljubljana", "Europe/London", "Europe/Luxembourg", "Europe/Madrid", "Europe/Malta", "Europe/Mariehamn", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Europe/Oslo", "Europe/Paris", "Europe/Podgorica", "Europe/Prague", "Europe/Riga", "Europe/Rome", "Europe/Samara", "Europe/San_Marino", "Europe/Sarajevo", "Europe/Saratov", "Europe/Simferopol", "Europe/Skopje", "Europe/Sofia", "Europe/Stockholm", "Europe/Tallinn", "Europe/Tirane", "Europe/Ulyanovsk", "Europe/Vaduz", "Europe/Vatican", "Europe/Vienna", "Europe/Vilnius", "Europe/Volgograd", "Europe/Warsaw", "Europe/Zagreb", "Europe/Zurich", "Indian/Antananarivo", "Indian/Chagos", "Indian/Christmas", "Indian/Cocos", "Indian/Comoro", "Indian/Kerguelen", "Indian/Mahe", "Indian/Maldives", "Indian/Mauritius", "Indian/Mayotte", "Indian/Reunion", "Pacific/Apia", "Pacific/Auckland", "Pacific/Bougainville", "Pacific/Chatham", "Pacific/Chuuk", "Pacific/Easter", "Pacific/Efate", "Pacific/Fakaofo", "Pacific/Fiji", "Pacific/Funafuti", "Pacific/Galapagos", "Pacific/Gambier", "Pacific/Guadalcanal", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Kanton", "Pacific/Kiritimati", "Pacific/Kosrae", "Pacific/Kwajalein", "Pacific/Majuro", "Pacific/Marquesas", "Pacific/Midway", "Pacific/Nauru", "Pacific/Niue", "Pacific/Norfolk", "Pacific/Noumea", "Pacific/Pago_Pago", "Pacific/Palau", "Pacific/Pitcairn", "Pacific/Pohnpei", "Pacific/Port_Moresby", "Pacific/Rarotonga", "Pacific/Saipan", "Pacific/Tahiti", "Pacific/Tarawa", "Pacific/Tongatapu", "Pacific/Wake", "Pacific/Wallis", "UTC" ]); // src/api/application/users.ts var CreateSchema = z7.object({ email: z7.email(), external_id: z7.string().max(255).optional(), username: z7.string().min(1).max(255), password: z7.string().optional(), language: languagesSchema, timezone: timezonesSchema }); // src/api/application/nodes_allocations.ts import z8 from "zod"; // src/api/application/nodes.ts import z9 from "zod"; var NodeCreateSchema = z9.object({ name: z9.string().min(1).max(100), description: z9.string().optional(), public: z9.boolean().optional(), fqdn: z9.string().nonempty(), scheme: z9.enum(["http", "https"]), behind_proxy: z9.boolean().optional(), memory: z9.number().min(0), memory_overallocate: z9.number().min(-1), disk: z9.number().min(0), disk_overallocate: z9.number().min(-1), cpu: z9.number().min(0), cpu_overallocate: z9.number().min(-1), daemon_base: z9.string().nonempty().optional(), daemon_sftp: z9.number().min(1).max(65535), daemon_sftp_alias: z9.string().optional(), daemon_listen: z9.number().min(1).max(65535), daemon_connect: z9.number().min(1).max(65535), maintenance_mode: z9.boolean().optional(), upload_size: z9.number().min(1).max(1024), tags: z9.array(z9.string()).optional() }); // src/api/application/servers.ts import z11 from "zod"; // src/api/application/servers_databases.ts import z10 from "zod"; // src/api/application/servers.ts var CreateServerSchema = z11.object({ external_id: z11.string().min(1).max(255).optional(), name: z11.string().min(1).max(255), description: z11.string().optional(), user: z11.number(), egg: z11.number(), docker_image: z11.string().optional(), startup: z11.string().optional(), environment: z11.record(z11.string(), z11.string()), skip_scripts: z11.boolean().optional(), oom_killer: z11.boolean().optional(), start_on_completion: z11.boolean().optional(), docker_labels: z11.record(z11.string(), z11.string()).optional(), limits: z11.object({ memory: z11.number().min(0), swap: z11.number().min(-1), disk: z11.number().min(0), io: z11.number().min(0), threads: z11.string().optional(), cpu: z11.number().min(0) }), feature_limits: z11.object({ databases: z11.number().min(0), allocations: z11.number().min(0), backups: z11.number().min(0) }), allocation: z11.object({ default: z11.string(), additional: z11.array(z11.string()).optional() }).optional(), deploy: z11.object({ tags: z11.array(z11.string()).optional(), dedicated_ip: z11.boolean().optional(), port_range: z11.array(z11.string()).optional() }).optional() }); var UpdateDetailsSchema = CreateServerSchema.pick({ external_id: true, name: true, user: true, description: true, docker_labels: true }); var UpdateBuildSchema = CreateServerSchema.pick({ oom_killer: true, limits: true, feature_limits: true }).extend({ allocation: z11.number().optional(), add_allocations: z11.array(z11.string()).optional(), remove_allocations: z11.array(z11.string()).optional() }); var UpdateStartupSchema = CreateServerSchema.pick({ startup: true, environment: true, egg: true }).extend({ image: z11.string().optional(), skip_scripts: z11.boolean() }); // src/api/application/database_hosts.ts import z12 from "zod"; var CreateDBHostSchema = z12.object({ name: z12.string().min(1).max(255), host: z12.string(), port: z12.number().min(1).max(65535), username: z12.string().min(1).max(255), password: z12.string().optional(), node_ids: z12.array(z12.string()).optional(), max_databases: z12.number().optional() }); // src/api/application/mounts.ts import z13 from "zod"; var CreateMountSchema = z13.object({ name: z13.string().min(1).max(255), description: z13.string().optional(), source: z13.string(), target: z13.string(), read_only: z13.boolean().optional() }); // src/api/base/request.ts import z14 from "zod"; import axios3 from "axios"; // src/api/base/types.ts var PterodactylException = class extends Error { data; status; constructor(message, data, status) { super(message); this.data = data; this.status = status; } }; // src/api/base/request.ts var Agent = class { base_url; token; requester; constructor(url, token, type, suffix = "/api") { this.base_url = z14.url("Invalid URL Schema").transform((url2) => new URL(url2).href).parse(url); this.token = z14.string().regex(/^(ptl[ac]|pacc|papp)_.+$/, "Invalid token type").parse(token); this.requester = axios3.create({ baseURL: this.base_url.replace(/\/+$/, "") + `${suffix}/${type}`, timeout: 3e3, headers: { Authorization: `Bearer ${this.token}` } }); this.requester.interceptors.response.use(void 0, (error) => { if (error.response && error.response.status === 400) { return Promise.reject( new PterodactylException( "Invalid request data", error.response.data, error.response.status ) ); } return Promise.reject(error); }); } }; // src/api/index.ts var PelicanAPIClient = class extends Client { constructor(url, token, suffix = "/api") { const ax = new Agent(url, token, "client", suffix); super(ax.requester); } }; // src/humane/Account.ts var Account2 = class { client; uuid; username; $email; get email() { return this.$email; } language; image; admin; root_admin; $has2faEnabled; get has2faEnabled() { return this.$has2faEnabled; } createdAt; updatedAt; constructor(client, user) { this.client = client; this.uuid = user.uuid; this.username = user.username; this.$email = user.email; this.language = user.language; this.image = user.image; this.admin = user.admin; this.root_admin = user.root_admin; this.$has2faEnabled = user["2fa_enabled"]; this.createdAt = new Date(user.created_at); this.updatedAt = new Date(user.updated_at); } updateEmail = async (newEmail, password) => { await this.client.account.updateEmail(newEmail, password); this.$email = newEmail; }; updatePassword = async (newPassword) => this.client.account.updatePassword(newPassword); listApiKeys = async () => this.client.account.apiKeys.list(); createApiKey = async (description, allowed_ips) => this.client.account.apiKeys.create(description, allowed_ips); deleteApiKey = async (identifier) => this.client.account.apiKeys.delete(identifier); listSshKeys = async () => this.client.account.sshKeys.list(); createSshKey = async (name, public_key) => this.client.account.sshKeys.create(name, public_key); deleteSshKey = async (fingerprint) => this.client.account.sshKeys.delete(fingerprint); }; // src/humane/ServerAllocation.ts var ServerAllocation = class { client; alias; id; ip; $isDefault; get isDefault() { return this.$isDefault; } $notes; get notes() { return this.$notes; } port; constructor(client, alloc) { this.client = client; this.alias = alloc.ip_alias; this.id = alloc.id; this.ip = alloc.ip; this.$isDefault = alloc.is_default; this.$notes = alloc.notes; this.port = alloc.port; } setNotes = async (notes) => { const data = await this.client.allocations.setNotes(this.id, notes); this.$notes = data.notes; }; makeDefault = async () => { const data = await this.client.allocations.setPrimary(this.id); this.$isDefault = data.is_default; }; unassign = async () => this.client.allocations.unassign(this.id); }; // src/humane/ServerBackup.ts var ServerBackup = class { client; bytes; checksum; completedAt; createdAt; ignoredFiles; isLocked; isSuccessful; name; uuid; constructor(client, backup) { this.client = client; this.bytes = backup.bytes; this.checksum = backup.checksum; this.completedAt = backup.completed_at ? new Date(backup.completed_at) : null; this.createdAt = new Date(backup.created_at); this.ignoredFiles = backup.ignored_files; this.isLocked = backup.is_locked; this.isSuccessful = backup.is_successful; this.name = backup.name; this.uuid = backup.uuid; } downloadGetUrl = async () => this.client.backups.downloadGetUrl(this.uuid); download = async () => this.client.backups.download(this.uuid); delete = async () => this.client.backups.delete(this.uuid); rename = async (name) => this.client.backups.rename(this.uuid, name); toggleLock = async () => this.client.backups.toggleLock(this.uuid); restore = async (truncate) => this.client.backups.restore(this.uuid, truncate); }; // src/humane/ServerDatabase.ts var ServerDatabase = class { client; allowConnectionsFrom; host; port; id; maxConnections; name; $password; get password() { return this.$password; } username; constructor(client, database) { this.client = client; this.allowConnectionsFrom = database.connections_from; this.host = database.host.address; this.port = database.host.port; this.id = database.id; this.maxConnections = database.max_connections; this.name = database.name; this.$password = database.relationships?.password.attributes.password; this.username = database.username; } rotatePassword = async () => { const data = await this.client.databases.rotatePassword(this.id); this.$password = data.relationships?.password.attributes.password; }; delete = async () => this.client.databases.delete(this.id); }; // src/humane/ServerFile.ts import path from "path"; var ServerFile = class _ServerFile { client; dir; path; createdAt; isFile; isSymlink; mimetype; mode; modeBits; modifiedAt; name; size; constructor(client, file, dir = "/") { this.client = client; this.dir = dir; this.createdAt = new Date(file.created_at); this.isFile = file.is_file; this.isSymlink = file.is_symlink; this.mimetype = file.mimetype; this.mode = file.mode; this.modeBits = file.mode_bits; this.modifiedAt = new Date(file.modified_at); this.name = file.name; this.size = file.size; this.path = path.join(dir, this.name); } get isArchive() { return [ "zip", "tgz", "tar.gz", "txz", "tar.xz", "tbz2", "tar.bz2" ].some((ext) => this.name.endsWith(`.${ext}`)); } /** * Return the contents of a file. To read binary file (non-editable) use {@link download} instead */ contents = async () => this.client.files.contents(this.path); downloadGetUrl = async () => this.client.files.downloadGetUrl(this.path); download = async () => this.client.files.download(this.path); rename = async (newName) => this.client.files.rename(this.dir, [{ from: this.name, to: newName }]); copy = async () => this.client.files.copy(this.path); write = async (content) => this.client.files.write(this.path, content); compress = async (archive_name, extension) => new _ServerFile( this.client, await this.client.files.compress( this.dir, [this.name], archive_name, extension ) ); decompress = async () => this.client.files.decompress(this.dir, this.name); delete = async () => this.client.files.delete(this.dir, [this.name]); chmod = async (mode) => this.client.files.chmod(this.dir, [{ file: this.name, mode }]); }; // src/humane/ServerSchedule.ts var ServerSchedule = class { client; createdAt; $cron; get cron() { return { ...this.$cron }; } id; $isActive; get isActive() { return this.$isActive; } $isProcessing; get isProcessing() { return this.$isProcessing; } lastRunAt; $name; get name() { return this.$name; } nextRunAt; $onlyWhenOnline; get onlyWhenOnline() { return this.$onlyWhenOnline; } tasks; $updatedAt; get updatedAt() { return this.$updatedAt; } constructor(client, schedule) { this.client = client; this.createdAt = new Date(schedule.created_at); this.$cron = schedule.cron; this.id = schedule.id; this.$isActive = schedule.is_active; this.$isProcessing = schedule.is_processing; this.lastRunAt = schedule.last_run_at ? new Date(schedule.last_run_at) : null; this.$name = schedule.name; this.nextRunAt = new Date(schedule.next_run_at); this.$onlyWhenOnline = schedule.only_when_online; this.tasks = schedule.relationships.tasks.data.map( (d) => new ServerScheduleTask(this.client, this.id, d.attributes) ); this.$updatedAt = new Date(schedule.updated_at); } update = async (opts) => { const data = await this.client.schedules.control(this.id).update(opts); this.$name = data.name; this.$isActive = data.is_active; this.$isProcessing = data.is_processing; this.$onlyWhenOnline = data.only_when_online; this.$cron = data.cron