@pelican.ts/sdk
Version:
Pelican panel SDK for TypeScript
1,836 lines (1,803 loc) • 63.1 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
Account: () => Account2,
Client: () => Client3,
Server: () => Server,
ServerAllocation: () => ServerAllocation,
ServerBackup: () => ServerBackup,
ServerDatabase: () => ServerDatabase,
ServerFile: () => ServerFile,
ServerSchedule: () => ServerSchedule,
ServerUser: () => ServerUser,
createPelicanClient: () => createPelicanClient
});
module.exports = __toCommonJS(index_exports);
// src/api/client/account.ts
var import_zod = __toESM(require("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 = import_zod.default.email().parse(newEmail);
await this.r.put("/account/email", { email: newEmail, password });
};
updatePassword = async (newPassword) => {
newPassword = import_zod.default.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 = import_zod.default.array(import_zod.default.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
var import_zod5 = __toESM(require("zod"));
// src/api/client/server_databases.ts
var import_zod2 = __toESM(require("zod"));
var ServerDatabases = class {
r;
id;
constructor(requester, id) {
this.r = requester;
this.id = id;
}
list = async (include, page = 1) => {
import_zod2.default.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
var import_axios = __toESM(require("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 import_axios.default.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 import_axios.default.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
var import_axios2 = __toESM(require("axios"));
var import_zod3 = __toESM(require("zod"));
var ServerBackups = class {
r;
id;
constructor(requester, id) {
this.r = requester;
this.id = id;
}
list = async (page = 1) => {
import_zod3.default.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 = import_zod3.default.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 import_axios2.default.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
var import_zod4 = __toESM(require("zod"));
var ServerSettings = class {
r;
id;
constructor(requester, id) {
this.r = requester;
this.id = id;
}
rename = async (name) => {
name = import_zod4.default.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
var import_events = require("events");
var import_isomorphic_ws = __toESM(require("isomorphic-ws"));
var import_strip_color = __toESM(require("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 import_events.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 import_isomorphic_ws.default(socketUrl) : new import_isomorphic_ws.default(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 = (0, import_strip_color.default)(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 = (0, import_strip_color.default)(output);
}
this.emit("daemon message" /* DAEMON_MESSAGE */, output);
break;
}
case "install output" /* INSTALL_OUTPUT */: {
let output = message.args[0];
if (this.stripColors) {
output = (0, import_strip_color.default)(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) => {
import_zod5.default.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
var import_zod7 = __toESM(require("zod"));
// src/api/common/types/enums.ts
var import_zod6 = __toESM(require("zod"));
var languagesSchema = import_zod6.default.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 = import_zod6.default.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 = import_zod7.default.object({
email: import_zod7.default.email(),
external_id: import_zod7.default.string().max(255).optional(),
username: import_zod7.default.string().min(1).max(255),
password: import_zod7.default.string().optional(),
language: languagesSchema,
timezone: timezonesSchema
});
// src/api/application/nodes_allocations.ts
var import_zod8 = __toESM(require("zod"));
// src/api/application/nodes.ts
var import_zod9 = __toESM(require("zod"));
var NodeCreateSchema = import_zod9.default.object({
name: import_zod9.default.string().min(1).max(100),
description: import_zod9.default.string().optional(),
public: import_zod9.default.boolean().optional(),
fqdn: import_zod9.default.string().nonempty(),
scheme: import_zod9.default.enum(["http", "https"]),
behind_proxy: import_zod9.default.boolean().optional(),
memory: import_zod9.default.number().min(0),
memory_overallocate: import_zod9.default.number().min(-1),
disk: import_zod9.default.number().min(0),
disk_overallocate: import_zod9.default.number().min(-1),
cpu: import_zod9.default.number().min(0),
cpu_overallocate: import_zod9.default.number().min(-1),
daemon_base: import_zod9.default.string().nonempty().optional(),
daemon_sftp: import_zod9.default.number().min(1).max(65535),
daemon_sftp_alias: import_zod9.default.string().optional(),
daemon_listen: import_zod9.default.number().min(1).max(65535),
daemon_connect: import_zod9.default.number().min(1).max(65535),
maintenance_mode: import_zod9.default.boolean().optional(),
upload_size: import_zod9.default.number().min(1).max(1024),
tags: import_zod9.default.array(import_zod9.default.string()).optional()
});
// src/api/application/servers.ts
var import_zod11 = __toESM(require("zod"));
// src/api/application/servers_databases.ts
var import_zod10 = __toESM(require("zod"));
// src/api/application/servers.ts
var CreateServerSchema = import_zod11.default.object({
external_id: import_zod11.default.string().min(1).max(255).optional(),
name: import_zod11.default.string().min(1).max(255),
description: import_zod11.default.string().optional(),
user: import_zod11.default.number(),
egg: import_zod11.default.number(),
docker_image: import_zod11.default.string().optional(),
startup: import_zod11.default.string().optional(),
environment: import_zod11.default.record(import_zod11.default.string(), import_zod11.default.string()),
skip_scripts: import_zod11.default.boolean().optional(),
oom_killer: import_zod11.default.boolean().optional(),
start_on_completion: import_zod11.default.boolean().optional(),
docker_labels: import_zod11.default.record(import_zod11.default.string(), import_zod11.default.string()).optional(),
limits: import_zod11.default.object({
memory: import_zod11.default.number().min(0),
swap: import_zod11.default.number().min(-1),
disk: import_zod11.default.number().min(0),
io: import_zod11.default.number().min(0),
threads: import_zod11.default.string().optional(),
cpu: import_zod11.default.number().min(0)
}),
feature_limits: import_zod11.default.object({
databases: import_zod11.default.number().min(0),
allocations: import_zod11.default.number().min(0),
backups: import_zod11.default.number().min(0)
}),
allocation: import_zod11.default.object({
default: import_zod11.default.string(),
additional: import_zod11.default.array(import_zod11.default.string()).optional()
}).optional(),
deploy: import_zod11.default.object({
tags: import_zod11.default.array(import_zod11.default.string()).optional(),
dedicated_ip: import_zod11.default.boolean().optional(),
port_range: import_zod11.default.array(import_zod11.default.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: import_zod11.default.number().optional(),
add_allocations: import_zod11.default.array(import_zod11.default.string()).optional(),
remove_allocations: import_zod11.default.array(import_zod11.default.string()).optional()
});
var UpdateStartupSchema = CreateServerSchema.pick({
startup: true,
environment: true,
egg: true
}).extend({ image: import_zod11.default.string().optional(), skip_scripts: import_zod11.default.boolean() });
// src/api/application/database_hosts.ts
var import_zod12 = __toESM(require("zod"));
var CreateDBHostSchema = import_zod12.default.object({
name: import_zod12.default.string().min(1).max(255),
host: import_zod12.default.string(),
port: import_zod12.default.number().min(1).max(65535),
username: import_zod12.default.string().min(1).max(255),
password: import_zod12.default.string().optional(),
node_ids: import_zod12.default.array(import_zod12.default.string()).optional(),
max_databases: import_zod12.default.number().optional()
});
// src/api/application/mounts.ts
var import_zod13 = __toESM(require("zod"));
var CreateMountSchema = import_zod13.default.object({
name: import_zod13.default.string().min(1).max(255),
description: import_zod13.default.string().optional(),
source: import_zod13.default.string(),
target: import_zod13.default.string(),
read_only: import_zod13.default.boolean().optional()
});
// src/api/base/request.ts
var import_zod14 = __toESM(require("zod"));
var import_axios3 = __toESM(require("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 = import_zod14.default.url("Invalid URL Schema").transform((url2) => new URL(url2).href).parse(url);
this.token = import_zod14.default.string().regex(/^(ptl[ac]|pacc|papp)_.+$/, "Invalid token type").parse(token);
this.requester = import_axios3.default.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;
allowConnections