@devnote-dev/pterojs
Version:
A verbose API library for Pterodactyl
1,759 lines (1,738 loc) • 108 kB
JavaScript
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 __name = (target, value) => __defProp(target, "name", { value, configurable: true });
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(
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 src_exports = {};
__export(src_exports, {
Account: () => Account,
ApplicationDatabaseManager: () => ApplicationDatabaseManager,
ApplicationServer: () => ApplicationServer,
ApplicationServerManager: () => ApplicationServerManager,
BackupManager: () => BackupManager,
BaseManager: () => BaseManager,
BaseUser: () => BaseUser,
Builder: () => Builder,
ClientDatabaseManager: () => ClientDatabaseManager,
ClientServer: () => ClientServer,
ClientServerManager: () => ClientServerManager,
Dict: () => Dict,
FileManager: () => FileManager,
Flags: () => Flags,
NestEggsManager: () => NestEggsManager,
NestManager: () => NestManager,
NetworkManager: () => NetworkManager,
Node: () => Node,
NodeAllocationManager: () => NodeAllocationManager,
NodeBuilder: () => NodeBuilder,
NodeLocationManager: () => NodeLocationManager,
NodeManager: () => NodeManager,
Permissions: () => Permissions,
PteroAPIError: () => PteroAPIError,
PteroApp: () => PteroApp,
PteroClient: () => PteroClient,
RequestError: () => RequestError,
RequestManager: () => RequestManager,
Schedule: () => Schedule,
ScheduleManager: () => ScheduleManager,
ServerBuilder: () => ServerBuilder,
ServerStatus: () => ServerStatus,
Shard: () => Shard,
ShardStatus: () => ShardStatus,
SubUser: () => SubUser,
SubUserManager: () => SubUserManager,
User: () => User,
UserBuilder: () => UserBuilder,
UserManager: () => UserManager,
ValidationError: () => ValidationError,
WebSocketError: () => WebSocketError,
WebSocketManager: () => WebSocketManager,
buildQuery: () => buildQuery,
caseConv: () => caseConv_default,
configLoader: () => config_default,
escape: () => escape_default,
version: () => version2
});
module.exports = __toCommonJS(src_exports);
// package.json
var version = "2.2.2";
// src/structures/BaseManager.ts
var BaseManager = class {
constructor() {
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
getQueryOptions() {
return {
filters: this.FILTERS,
sorts: this.SORTS,
includes: this.INCLUDES
};
}
async getFetchAll(...options) {
const opts = options[options.length - 1] || {
page: 1
};
let data = await this.fetch(...options);
if (this.meta.totalPages > 1) {
for (let i = 2; i <= this.meta.totalPages; i++) {
opts.page = i;
let page = await this.fetch(opts);
data.update(page);
}
}
return data;
}
};
__name(BaseManager, "BaseManager");
// src/structures/Dict.ts
var _Dict = class extends Map {
constructor() {
super(...arguments);
this._limit = 0;
}
get limit() {
return this._limit;
}
setLimit(amount) {
if (this._limit)
throw new Error("Cannot override a set limit.");
this._limit = amount < 0 ? 0 : amount;
}
isLimited() {
return !!this._limit && super.size === this._limit;
}
set(key, value) {
if (this.isLimited())
throw new Error(`Dict has reached its limit (${this._limit})`);
return super.set(key, value);
}
some(fn) {
for (const [k, v] of this)
if (fn(v, k, this))
return true;
return false;
}
every(fn) {
for (const [k, v] of this)
if (!fn(v, k, this))
return false;
return true;
}
hasAny(...keys) {
return keys.some((k) => super.has(k));
}
hasAll(...keys) {
return keys.every((k) => super.has(k));
}
first(amount) {
const v = [...super.values()];
if (amount === void 0)
return v[0];
const s = v.splice(0, amount);
return s.length === 1 ? s[0] : s;
}
firstKey(amount) {
const k = [...super.keys()];
if (amount === void 0)
return k[0];
const s = k.splice(0, amount);
return s.length === 1 ? s[0] : s;
}
last(amount) {
const v = [...super.values()];
if (amount === void 0)
return v[v.length - 1];
const s = v.slice(-amount);
return s.length === 1 ? s[0] : s;
}
lastKey(amount) {
const k = [...super.keys()];
if (amount === void 0)
return k[k.length - 1];
const s = k.slice(-amount);
return s.length === 1 ? s[0] : s;
}
random(amount) {
const v = [...super.values()];
if (amount === void 0)
return v[Math.floor(Math.random() * v.length)];
const s = [];
for (let i = 0; i < amount; i++)
s.push(v[Math.floor(Math.random() * v.length)]);
return s.length === 1 ? s[0] : s;
}
randomKey(amount) {
const k = [...super.keys()];
if (amount === void 0)
return k[Math.floor(Math.random() * k.length)];
const s = [];
for (let i = 0; i < amount; i++)
s.push(k[Math.floor(Math.random() * k.length)]);
return s.length === 1 ? s[0] : s;
}
map(fn) {
const res = [];
for (const [k, v] of this)
res.push(fn(v, k, this));
return res;
}
filter(fn) {
const res = new _Dict();
for (const [k, v] of this)
if (fn(v, k, this))
res.set(k, v);
return res;
}
find(fn) {
for (const [k, v] of this)
if (fn(v, k, this))
return v;
return void 0;
}
sweep(fn) {
let res = 0;
for (const [k, v] of this)
if (fn(v, k, this))
super.delete(k) && res++;
return res;
}
part(fn) {
const pass = new _Dict();
const fail = new _Dict();
for (const [k, v] of this)
if (fn(v, k, this))
pass.set(k, v);
else
fail.set(k, v);
return [pass, fail];
}
reduce(fn, acc) {
for (const [k, v] of this)
acc = fn(v, k, this);
return acc;
}
join(...dict) {
const res = this.clone();
for (const d of dict)
for (const [k, v] of d)
res.set(k, v);
return res;
}
difference(dict) {
const res = new _Dict();
for (const [k, v] of this)
if (!dict.has(k))
res.set(k, v);
for (const [k, v] of dict)
if (!super.has(k))
res.set(k, v);
return res;
}
update(dict) {
for (const [k, v] of dict)
this.set(k, v);
}
clone() {
return new _Dict(super.entries());
}
};
var Dict = _Dict;
__name(Dict, "Dict");
"constructor";
// src/structures/Errors.ts
var PteroAPIError = class extends Error {
constructor(data) {
const fmt = data.errors.map((e) => `- ${e.status}: ${e.detail || "No details provided"}`).join("\n");
super("\n" + fmt);
this.codes = data.errors.map((e) => e.code);
this.meta = data.errors.map((e) => e.meta).filter(Boolean);
}
};
__name(PteroAPIError, "PteroAPIError");
var RequestError = class extends Error {
};
__name(RequestError, "RequestError");
var ValidationError = class extends Error {
constructor(...args) {
switch (args.length) {
case 3:
super(
`Failed to validate ${args[0]}: expected ${args[1]}; got ${args[2]}`
);
break;
case 2:
break;
case 1:
super(`Validation: ${args[0]}`);
break;
default:
super("Validation check failed.");
break;
}
}
};
__name(ValidationError, "ValidationError");
var WebSocketError = class extends Error {
};
__name(WebSocketError, "WebSocketError");
// src/util/caseConv.ts
function camelCase(str) {
let res = "";
let next = false;
str.split("").forEach((c) => {
if (next) {
next = false;
res += c.toUpperCase();
} else if (c === "_") {
next = true;
} else {
res += c;
}
});
return res;
}
__name(camelCase, "camelCase");
function toCamelCase(obj, options = {}) {
if (typeof obj !== "object")
return obj;
const parsed = {};
if (Array.isArray(obj)) {
return obj.map((i) => toCamelCase(i));
}
for (let [k, v] of Object.entries(obj)) {
if (options.ignore?.includes(k))
continue;
if (options.map?.[k])
k = options.map[k];
if (options.cast?.[k]) {
try {
const cls = options.cast[k];
v = new cls(v);
} catch {
v = String(v);
}
}
if (Array.isArray(v)) {
v = v.map((i) => toCamelCase(i));
} else if (typeof v === "object" && !!v) {
v = toCamelCase(v);
}
parsed[camelCase(k)] = v;
}
return parsed;
}
__name(toCamelCase, "toCamelCase");
function snakeCase(str) {
let res = "";
const isUpper = /* @__PURE__ */ __name((c) => "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("").includes(c), "isUpper");
str.split("").forEach((c) => {
if (isUpper(c))
res += "_";
res += c.toLowerCase();
});
return res;
}
__name(snakeCase, "snakeCase");
function toSnakeCase(obj, options = {}) {
if (typeof obj !== "object")
return obj;
const parsed = {};
if (Array.isArray(obj)) {
return obj.map((i) => toSnakeCase(i));
}
for (let [k, v] of Object.entries(obj)) {
if (options.ignore?.includes(k))
continue;
if (options.map?.[k])
k = options.map[k];
if (options.cast?.[k]) {
try {
const cls = options.cast[k];
v = new cls(v);
} catch {
v = String(v);
}
}
if (Array.isArray(v)) {
v = v.map((i) => toSnakeCase(i));
} else if (typeof v === "object" && !!v) {
v = toSnakeCase(v);
}
parsed[snakeCase(k)] = v;
}
return parsed;
}
__name(toSnakeCase, "toSnakeCase");
var caseConv_default = {
toCamelCase,
toSnakeCase
};
// src/application/endpoints.ts
var endpoints_default = {
users: {
main: "/users",
get: (u) => `/users/${u}`,
ext: (u) => `/users/external/${u}`
},
nodes: {
main: "/nodes",
get: (n) => `/nodes/${n}`,
deploy: "/nodes/deployable",
config: (n) => `/nodes/${n}/configuration`,
allocations: {
main: (n) => `/nodes/${n}/allocations`,
get: (n, a) => `/nodes/${n}/allocations/${a}`
}
},
servers: {
main: "/servers",
get: (s) => `/servers/${s}`,
ext: (s) => `/servers/external/${s}`,
details: (s) => `/servers/${s}/details`,
build: (s) => `/servers/${s}/build`,
startup: (s) => `/servers/${s}/startup`,
suspend: (s) => `/servers/${s}/suspend`,
unsuspend: (s) => `/servers/${s}/unsuspend`,
reinstall: (s) => `/servers/${s}/reinstall`,
databases: {
main: (s) => `/servers/${s}/databases`,
get: (s, id) => `/servers/${s}/databases/${id}`,
reset: (s, id) => `/servers/${s}/databases/${id}/reset-password`
}
},
locations: {
main: "/locations",
get: (l) => `/locations/${l}`
},
nests: {
main: "/nests",
get: (n) => `/nests/${n}`,
eggs: {
main: (n) => `/nests/${n}/eggs`,
get: (n, e) => `/nests/${n}/eggs/${e}`
}
}
};
// src/application/ApplicationDatabaseManager.ts
var ApplicationDatabaseManager = class extends BaseManager {
constructor(client, serverId) {
super();
this.client = client;
this.cache = new Dict();
this.serverId = serverId;
}
get FILTERS() {
return Object.freeze([]);
}
get INCLUDES() {
return Object.freeze(["host", "password"]);
}
get SORTS() {
return Object.freeze([]);
}
_patch(data) {
if (data.data) {
const res = new Dict();
for (let o of data.data) {
const d2 = caseConv_default.toCamelCase(
o.attributes
);
}
this.cache.update(res);
return res;
}
const d = caseConv_default.toCamelCase(data.attributes);
this.cache.set(d.id, d);
return d;
}
async fetch(op, ops = {}) {
let path;
switch (typeof op) {
case "number": {
if (!ops.force && this.cache.has(op))
return this.cache.get(op);
path = endpoints_default.servers.databases.get(this.serverId, op);
break;
}
case "undefined":
case "object": {
path = endpoints_default.servers.databases.main(this.serverId);
if (op)
ops = op;
break;
}
default:
throw new ValidationError(
`expected database id or fetch options; got ${typeof op}`
);
}
const data = await this.client.requests.get(path, ops, null, this);
return this._patch(data);
}
async create(database, remote, host) {
if (!/^[0-9%.]{1,15}$/.test(remote))
throw new ValidationError(
"remote did not pass the required validation: /^[0-9%.]{1,15}$/"
);
const data = await this.client.requests.post(
endpoints_default.servers.databases.main(this.serverId),
{ database, remote, host }
);
return this._patch(data);
}
async resetPasword(id) {
await this.client.requests.post(
endpoints_default.servers.databases.reset(this.serverId, id)
);
}
async delete(id) {
await this.client.requests.delete(
endpoints_default.servers.databases.get(this.serverId, id)
);
this.cache.delete(id);
}
};
__name(ApplicationDatabaseManager, "ApplicationDatabaseManager");
// src/structures/ApplicationServer.ts
var ApplicationServer = class {
constructor(client, data) {
this.client = client;
this.databases = new ApplicationDatabaseManager(client, data.id);
this.id = data.id;
this.uuid = data.uuid;
this.identifier = data.identifier;
this.createdAt = new Date(data.created_at);
this.createdTimestamp = this.createdAt.getTime();
this._patch(data);
}
_patch(data) {
if ("external_id" in data)
this.externalId = data.external_id;
if ("name" in data)
this.name = data.name;
if ("description" in data)
this.description = data.description || void 0;
if ("status" in data)
this.status = data.status;
if ("suspended" in data)
this.suspended = data.suspended;
if ("limits" in data)
this.limits = caseConv_default.toCamelCase(data.limits);
if ("feature_limits" in data)
this.featureLimits = data.feature_limits;
if ("user" in data)
this.ownerId = data.user;
if ("node" in data)
this.nodeId = data.node;
if ("allocation" in data)
this.allocation = data.allocation;
if ("nest" in data)
this.nest = data.nest;
if ("egg" in data)
this.egg = data.egg;
if ("container" in data) {
this.container = caseConv_default.toCamelCase(data.container, {
ignore: ["environment"]
});
this.container.environment = data.container.environment;
this.container.installed = !!this.container.installed;
}
if ("relationships" in data) {
this.owner = "user" in data.relationships ? this.client.users.resolve(data) : void 0;
this.node = "node" in data.relationships ? this.client.nodes.resolve(data) : void 0;
}
}
get panelURL() {
return `${this.client.domain}/server/${this.identifier}`;
}
get adminURL() {
return `${this.client.domain}/admin/servers/view/${this.id}`;
}
async fetchOwner() {
if (this.owner)
return this.owner;
const user = await this.client.users.fetch(this.ownerId, {
force: true
});
this.owner = user;
return user;
}
async updateDetails(options) {
const data = await this.client.servers.updateDetails(this.id, options);
this._patch(data.toJSON());
return this;
}
async updateBuild(options) {
const data = await this.client.servers.updateBuild(this.id, options);
this._patch(data);
return this;
}
async updateStartup(options) {
const data = await this.client.servers.updateStartup(this.id, options);
this._patch(data);
return this;
}
async suspend() {
await this.client.servers.suspend(this.id);
}
async unsuspend() {
await this.client.servers.unsuspend(this.id);
}
async reinstall() {
await this.client.servers.reinstall(this.id);
}
toJSON() {
return caseConv_default.toSnakeCase(this, {
ignore: ["client", "user", "node"],
map: { ownerId: "user", nodeId: "node" }
});
}
toString() {
return this.name;
}
};
__name(ApplicationServer, "ApplicationServer");
// src/application/ApplicationServerManager.ts
var ApplicationServerManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
get FILTERS() {
return Object.freeze([
"name",
"uuid",
"uuidShort",
"externalId",
"image"
]);
}
get INCLUDES() {
return Object.freeze([
"allocations",
"user",
"subusers",
"nest",
"egg",
"variables",
"location",
"node",
"databases"
]);
}
get SORTS() {
return Object.freeze(["id", "-id", "uuid", "-uuid"]);
}
get defaultLimits() {
return {
memory: 128,
swap: 0,
disk: 512,
io: 500,
cpu: 100,
threads: null
};
}
get defaultFeatureLimits() {
return {
allocations: 1,
databases: 1,
backups: 1
};
}
_patch(data) {
if (data?.meta?.pagination) {
this.meta = caseConv_default.toCamelCase(data.meta.pagination, {
ignore: ["current_page"]
});
this.meta.current = data.meta.pagination.current_page;
}
if (data.data) {
const res = new Dict();
for (let o of data.data) {
const s2 = new ApplicationServer(this.client, o.attributes);
res.set(s2.id, s2);
}
if (this.client.options.servers.cache)
this.cache.update(res);
return res;
}
const s = new ApplicationServer(this.client, data.attributes);
if (this.client.options.servers.cache)
this.cache.set(s.id, s);
return s;
}
resolve(obj) {
if (obj instanceof ApplicationServer)
return obj;
if (typeof obj === "number")
return this.cache.get(obj);
if (typeof obj === "string")
return this.cache.find((s) => s.name === obj);
if (obj.relationships?.servers)
return this._patch(obj.relationships.servers);
return void 0;
}
adminURLFor(id) {
return `${this.client.domain}/admin/servers/view/${id}`;
}
panelURLFor(id) {
return `${this.client.domain}/server/${id}`;
}
async fetch(op, ops = {}) {
let path;
switch (typeof op) {
case "number": {
if (!ops.force && this.cache.has(op))
return this.cache.get(op);
path = endpoints_default.servers.get(op);
break;
}
case "string": {
if (!ops.force) {
const u = this.cache.find((u2) => u2.externalId === op);
if (u)
return u;
}
path = endpoints_default.servers.ext(op);
break;
}
case "undefined":
case "object": {
path = endpoints_default.servers.main;
if (op)
ops = op;
break;
}
default:
throw new ValidationError(
`expected server id, external id or fetch options; got ${typeof op}`
);
}
const data = await this.client.requests.get(path, ops, null, this);
return this._patch(data);
}
fetchAll(options) {
return this.getFetchAll(options);
}
async query(entity, options) {
if (!options.sort && !options.filter)
throw new ValidationError("Sort or filter is required.");
if (options.filter === "identifier")
options.filter = "uuidShort";
if (options.filter === "externalId")
options.filter = "external_id";
const payload = {};
if (options.filter)
payload.filter = [options.filter, entity];
if (options.sort)
payload.sort = options.sort;
const data = await this.client.requests.get(
endpoints_default.servers.main,
payload,
null,
this
);
return this._patch(data);
}
async create(options) {
options.limits = Object.assign(
this.defaultLimits,
options.limits || {}
);
options.featureLimits = Object.assign(
this.defaultFeatureLimits,
options.featureLimits || {}
);
const payload = caseConv_default.toSnakeCase(options, {
ignore: ["environment"]
});
payload.environment = options.environment;
const data = await this.client.requests.post(
endpoints_default.servers.main,
payload
);
return this._patch(data);
}
async updateDetails(id, options) {
if (!Object.keys(options).length)
throw new ValidationError("Too few options to update the server.");
const server = await this.fetch(id, { force: true });
options.name ||= server.name;
options.owner ??= server.ownerId;
options.externalId ||= server.externalId;
options.description ||= server.description;
const payload = caseConv_default.toSnakeCase(options, {
map: { owner: "user" }
});
const data = await this.client.requests.patch(
endpoints_default.servers.details(id),
payload
);
return this._patch(data);
}
async updateBuild(id, options) {
if (!Object.keys(options).length)
throw new ValidationError("Too few options to update the server.");
const server = await this.fetch(id, { force: true });
options.limits = Object.assign(server.limits, options.limits);
options.featureLimits = Object.assign(
server.featureLimits,
options.featureLimits
);
options.allocation ??= server.allocation;
const data = await this.client.requests.patch(
endpoints_default.servers.build(id),
caseConv_default.toSnakeCase(options)
);
return this._patch(data);
}
async updateStartup(id, options) {
if (!Object.keys(options).length)
throw new ValidationError("Too few options to update the server.");
const server = await this.fetch(id, { force: true });
options.egg ??= server.egg;
options.environment ||= server.container.environment;
options.image ||= server.container.image;
options.skipScripts ??= false;
options.startup ||= server.container.startupCommand;
const payload = caseConv_default.toSnakeCase(options, {
ignore: ["environment"]
});
payload.environment = options.environment;
const data = await this.client.requests.patch(
endpoints_default.servers.startup(id),
payload
);
return this._patch(data);
}
suspend(id) {
return this.client.requests.post(endpoints_default.servers.suspend(id));
}
unsuspend(id) {
return this.client.requests.post(endpoints_default.servers.unsuspend(id));
}
reinstall(id) {
return this.client.requests.post(endpoints_default.servers.reinstall(id));
}
async delete(id, force = false) {
await this.client.requests.delete(
endpoints_default.servers.get(id) + (force ? "/force" : "")
);
this.cache.delete(id);
}
};
__name(ApplicationServerManager, "ApplicationServerManager");
// src/application/NestEggsManager.ts
var NestEggsManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
}
get FILTERS() {
return Object.freeze([]);
}
get INCLUDES() {
return Object.freeze([
"nest",
"servers",
"config",
"script",
"variables"
]);
}
get SORTS() {
return Object.freeze([]);
}
_patch(data) {
if (data?.data) {
const res = new Dict();
for (let o of data.data) {
let e2 = caseConv_default.toCamelCase(o.attributes);
e2.createdAt = new Date(e2.createdAt);
e2.updatedAt &&= new Date(e2.updatedAt);
res.set(e2.id, e2);
}
this.cache.update(res);
return res;
}
let e = caseConv_default.toCamelCase(data.attributes);
e.createdAt = new Date(e.createdAt);
e.updatedAt &&= new Date(e.updatedAt);
this.cache.set(e.id, e);
return e;
}
adminURLFor(id) {
return `${this.client.domain}/admin/nests/egg/${id}`;
}
async fetch(nest, op1, op2 = {}) {
let path = endpoints_default.nests.eggs.main(nest);
if (typeof op1 === "number") {
if (!op2.force && this.cache.has(op1))
return this.cache.get(op1);
path = endpoints_default.nests.eggs.get(nest, op1);
} else {
if (op1)
op2 = op1;
}
const data = await this.client.requests.get(path, op2, null, this);
return this._patch(data);
}
};
__name(NestEggsManager, "NestEggsManager");
// src/application/NestManager.ts
var NestManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
this.eggs = new NestEggsManager(client);
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
get FILTERS() {
return Object.freeze([]);
}
get INCLUDES() {
return Object.freeze(["eggs", "servers"]);
}
get SORTS() {
return Object.freeze([]);
}
_patch(data) {
if (data?.meta?.pagination) {
this.meta = caseConv_default.toCamelCase(data.meta.pagination, {
ignore: ["current_page"]
});
this.meta.current = data.meta.pagination.current_page;
}
if (data?.data) {
const res = new Dict();
for (let o of data.data) {
const n2 = caseConv_default.toCamelCase(o.attributes);
n2.createdAt = new Date(n2.createdAt);
n2.updatedAt &&= new Date(n2.updatedAt);
res.set(n2.id, n2);
}
if (this.client.options.nests.cache)
this.cache.update(res);
return res;
}
const n = caseConv_default.toCamelCase(data.attributes);
n.createdAt = new Date(n.createdAt);
n.updatedAt &&= new Date(n.updatedAt);
if (this.client.options.nodes.cache)
this.cache.set(n.id, n);
return n;
}
adminURLFor(id) {
return `${this.client.domain}/admin/nests/view/${id}`;
}
async fetch(op, include = []) {
let path = endpoints_default.nests.main;
if (typeof op === "number") {
path = endpoints_default.nests.get(op);
} else {
include.push(...op || []);
}
const data = await this.client.requests.get(
path,
{ include },
null,
this
);
return this._patch(data);
}
};
__name(NestManager, "NestManager");
// src/application/NodeAllocationManager.ts
var NodeAllocationManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
get FILTERS() {
return Object.freeze([]);
}
get INCLUDES() {
return Object.freeze(["node", "server"]);
}
get SORTS() {
return Object.freeze([]);
}
_patch(node, data) {
if (data?.meta?.pagination) {
this.meta = caseConv_default.toCamelCase(data.meta.pagination, {
ignore: ["current_page"]
});
this.meta.current = data.meta.pagination.current_page;
}
const res = new Dict();
for (let o of data.data) {
const a = caseConv_default.toCamelCase(o.attributes);
res.set(a.id, a);
}
const all = (this.cache.get(node) || new Dict()).join(res);
this.cache.set(node, all);
return res;
}
adminURLFor(id) {
return `${this.client.domain}/admin/nodes/view/${id}/allocation`;
}
async fetch(node, options = {}) {
if (!options.force) {
const a = this.cache.get(node);
if (a)
return Promise.resolve(a);
}
const data = await this.client.requests.get(
endpoints_default.nodes.allocations.main(node),
options,
null,
this
);
return this._patch(node, data);
}
fetchAll(node, options) {
return this.getFetchAll(node, options);
}
async fetchAvailable(node, single) {
const all = await this.fetchAll(node, { force: true });
return single ? all.filter((a) => !a.assigned).first() : all.filter((a) => !a.assigned);
}
async create(node, ip, ports) {
if (!ports.every((p) => typeof p === "string"))
throw new TypeError(
"Allocation ports must be a string integer or string range."
);
for (const port of ports) {
if (!port.includes("-"))
continue;
const [_start, _stop] = port.split("-");
const start = Number(_start), stop = Number(_stop);
if (start > stop)
throw new RangeError("Start cannot be greater than stop.");
if (start <= 1024 || stop > 65535)
throw new RangeError(
"Port range must be between 1024 and 65535."
);
if (stop - start > 1e3)
throw new RangeError("Maximum port range exceeded (1000).");
}
await this.client.requests.post(
endpoints_default.nodes.allocations.main(node),
{ ip, ports }
);
}
async delete(node, id) {
await this.client.requests.delete(
endpoints_default.nodes.allocations.get(node, id)
);
this.cache.get(node)?.delete(id);
}
};
__name(NodeAllocationManager, "NodeAllocationManager");
// src/application/NodeLocationManager.ts
var NodeLocationManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
get FILTERS() {
return Object.freeze(["short", "long"]);
}
get INCLUDES() {
return Object.freeze(["nodes", "servers"]);
}
get SORTS() {
return Object.freeze([]);
}
_patch(data) {
if (data?.meta?.pagination) {
this.meta = caseConv_default.toCamelCase(data.meta.pagination, {
ignore: ["current_page"]
});
this.meta.current = data.meta.pagination.current_page;
}
if (data?.data) {
const res = new Dict();
for (let o of data.data) {
const n = caseConv_default.toCamelCase(o.attributes);
n.createdAt = new Date(n.createdAt);
n.updatedAt &&= new Date(n.updatedAt);
res.set(n.id, n);
}
if (this.client.options.locations.cache)
this.cache.update(res);
return res;
}
const loc = caseConv_default.toCamelCase(data.attributes);
loc.createdAt = new Date(loc.createdAt);
loc.updatedAt &&= new Date(loc.updatedAt);
if (this.client.options.locations.cache)
this.cache.set(data.id, loc);
return loc;
}
resolve(obj) {
if (typeof obj === "number")
return this.cache.get(obj);
if (typeof obj === "string")
return this.cache.find((o) => o.short === obj || o.long === obj);
if (obj.relationships?.location?.attributes)
return this._patch(obj.relationships.location);
return void 0;
}
adminURLFor(id) {
return `${this.client.domain}/admin/locations/view/${id}`;
}
async fetch(op, ops = {}) {
let path = endpoints_default.locations.main;
if (typeof op === "number") {
if (!ops.force && this.cache.has(op))
return this.cache.get(op);
path = endpoints_default.locations.get(op);
} else {
if (op)
ops = op;
}
const data = await this.client.requests.get(path, ops, null, this);
return this._patch(data);
}
fetchAll(options) {
return this.getFetchAll(options);
}
async query(entity, options) {
if (!options.sort && !options.filter)
throw new ValidationError("Sort or filter is required.");
const payload = {};
if (options.filter)
payload.filter = [options.filter, entity];
if (options.sort)
payload.sort = options.sort;
const data = await this.client.requests.get(
endpoints_default.locations.main,
payload,
null,
this
);
return this._patch(data);
}
async create(short, long) {
const data = await this.client.requests.post(endpoints_default.locations.main, {
short,
long
});
return this._patch(data);
}
async update(id, options) {
if (!options.short && !options.long)
throw new ValidationError(
"Either short or long is required to update the location"
);
const data = await this.client.requests.patch(
endpoints_default.locations.get(id),
options
);
return this._patch(data);
}
async delete(id) {
await this.client.requests.delete(endpoints_default.locations.get(id));
this.cache.delete(id);
}
};
__name(NodeLocationManager, "NodeLocationManager");
// src/structures/Node.ts
var Node = class {
constructor(client, data) {
this.client = client;
this.id = data.id;
this.uuid = data.uuid;
this.createdAt = new Date(data.created_at);
this._patch(data);
}
_patch(data) {
if ("public" in data)
this.public = data.public;
if ("name" in data)
this.name = data.name;
if ("description" in data)
this.description = data.description || void 0;
if ("location_id" in data)
this.locationId = data.location_id;
if ("fqdn" in data)
this.fqdn = data.fqdn;
if ("scheme" in data)
this.scheme = data.scheme;
if ("behind_proxy" in data)
this.behindProxy = data.behind_proxy;
if ("maintenance_mode" in data)
this.maintenance = data.maintenance_mode;
if ("memory" in data)
this.memory = data.memory;
if ("memory_overallocate" in data)
this.overallocatedMemory = data.memory_overallocate;
if ("disk" in data)
this.disk = data.disk;
if ("disk_overallocate" in data)
this.overallocatedDisk = data.disk_overallocate;
if ("upload_size" in data)
this.uploadSize = data.upload_size;
if (!this.daemon)
this.daemon = {};
if ("daemon_listen" in data)
this.daemon.listening = data.daemon_listen;
if ("daemon_sftp" in data)
this.daemon.sftp = data.daemon_sftp;
if ("daemon_base" in data)
this.daemon.base = data.daemon_base;
}
get adminURL() {
return `${this.client.domain}/admin/nodes/view/${this.id}`;
}
async getConfig() {
return await this.client.nodes.getConfig(this.id);
}
async update(options) {
const data = await this.client.nodes.update(this.id, options);
this._patch(data.toJSON());
return this;
}
toJSON() {
return caseConv_default.toSnakeCase(this, {
ignore: ["client", "location", "servers"],
map: {
maintainance: "maintenance_mode",
overallocatedMemory: "memory_overallocate",
overallocatedDisk: "disk_overallocate"
}
});
}
toString() {
return this.name;
}
};
__name(Node, "Node");
// src/application/NodeManager.ts
var NodeManager = class extends BaseManager {
constructor(client) {
super();
this.client = client;
this.cache = new Dict();
this.meta = {
current: 0,
total: 0,
count: 0,
perPage: 0,
totalPages: 0
};
}
get FILTERS() {
return Object.freeze(["uuid", "name", "fqdn", "daemon_token_id"]);
}
get INCLUDES() {
return Object.freeze(["allocations", "location", "servers"]);
}
get SORTS() {
return Object.freeze(["id", "uuid", "memory", "disk"]);
}
_patch(data) {
if (data?.meta?.pagination) {
this.meta = caseConv_default.toCamelCase(data.meta.pagination, {
ignore: ["current_page"]
});
this.meta.current = data.meta.pagination.current_page;
}
if (data?.data) {
const res = new Dict();
for (const obj of data.data) {
const s = new Node(this.client, obj.attributes);
res.set(s.id, s);
}
if (this.client.options.servers.cache)
this.cache.update(res);
return res;
}
const n = new Node(this.client, data.attributes);
if (this.client.options.nodes.cache)
this.cache.set(n.id, n);
return n;
}
resolve(obj) {
if (obj instanceof Node)
return obj;
if (typeof obj === "number")
return this.cache.get(obj);
if (typeof obj === "string")
return this.cache.find((n) => n.name === obj);
if (obj.relationships?.node)
return this._patch(obj.relationships.node);
return void 0;
}
adminURLFor(id) {
return `${this.client.domain}/admin/nodes/view/${id}`;
}
async fetch(op, ops = {}) {
let path = endpoints_default.nodes.main;
if (typeof op === "number") {
if (!ops.force && this.cache.has(op))
return this.cache.get(op);
path = endpoints_default.nodes.get(op);
} else {
if (op)
ops = op;
}
const data = await this.client.requests.get(path, ops, null, this);
return this._patch(data);
}
fetchAll(options) {
return this.getFetchAll(options);
}
async fetchDeployable(options) {
const data = await this.client.requests.get(
endpoints_default.nodes.deploy,
void 0,
options
);
return this._patch(data);
}
async query(entity, options) {
if (!options.sort && !options.filter)
throw new ValidationError("Sort or filter is required.");
if (options.filter === "daemonTokenId")
options.filter = "daemon_token_id";
const payload = {};
if (options.filter)
payload.filter = [options.filter, entity];
if (options.sort)
payload.sort = options.sort;
const data = await this.client.requests.get(
endpoints_default.nodes.main,
payload,
null,
this
);
return this._patch(data);
}
async getConfig(id) {
const data = await this.client.requests.get(endpoints_default.nodes.config(id));
return caseConv_default.toCamelCase(data);
}
async create(options) {
const payload = caseConv_default.toSnakeCase(options);
const data = await this.client.requests.post(
endpoints_default.nodes.main,
payload
);
return this._patch(data);
}
async update(id, options) {
if (!Object.keys(options).length)
throw new ValidationError("Too few options to update the node.");
const _node = await this.fetch(id);
options = Object.assign(options, _node);
const payload = caseConv_default.toSnakeCase(options);
const data = await this.client.requests.patch(
endpoints_default.nodes.get(id),
payload
);
return this._patch(data);
}
async delete(id) {
await this.client.requests.delete(endpoints_default.nodes.get(id));
this.cache.delete(id);
}
};
__name(NodeManager, "NodeManager");
// src/http/RequestManager.ts
var import_axios = __toESM(require("axios"));
var import_events = require("events");
// src/util/query.ts
var buildQuery = /* @__PURE__ */ __name((args, allowed) => {
const parsed = [];
if (args.page)
parsed.push(`page=${args.page}`);
if (args.perPage && args.perPage > 0) {
if (args.perPage > 100)
args.perPage = 100;
parsed.push(`per_page=${args.perPage}`);
}
if (args.filter) {
if (!allowed.filters?.includes(args.filter[0]))
throw new ValidationError(
`Invalid filter argument '${args.filter[0]}'.`
);
parsed.push(`filter[${args.filter[0]}]=${args.filter[1]}`);
}
if (args.include) {
for (const arg of args.include) {
if (!allowed.includes.includes(arg))
throw new ValidationError(`Invalid include argument '${arg}'.`);
}
if (args.include?.length)
parsed.push(`include=${args.include}`);
}
if (args.sort) {
if (!allowed.sorts.includes(args.sort))
throw new ValidationError(`Invalid sort argument '${args.sort}'.`);
parsed.push(`sort=${args.sort}`);
}
if (!parsed.length)
return "";
return "?" + parsed.join("&");
}, "buildQuery");
// src/http/RequestManager.ts
var RequestManager = class extends import_events.EventEmitter {
constructor(_type, _domain, _auth) {
super();
this._type = _type;
this._domain = _domain;
this._auth = _auth;
this.instance = import_axios.default.create({
baseURL: `${this._domain}/api/${this._type.toLowerCase()}`
});
this._ping = -1;
this._start = 0;
}
emit(event, ...args) {
return super.emit(event, ...args);
}
on(event, listener) {
super.on(event, listener);
return this;
}
once(event, listener) {
super.once(event, listener);
return this;
}
off(event, listener) {
super.off(event, listener);
return this;
}
getHeaders() {
return {
"User-Agent": `PteroJS ${this._type} v${version}`,
"Content-Type": "application/json",
Accept: "application/json, text/plain",
Authorization: `Bearer ${this._auth}`
};
}
debug(...data) {
data.map((d) => `[HTTP] ${d}`).forEach((d) => super.emit("debug", d));
}
async _make(method, path, body) {
const headers = this.getHeaders();
if (body !== null && body !== void 0) {
if (typeof body === "string") {
headers["Content-Type"] = "text/plain";
} else {
body = JSON.stringify(body);
}
super.emit("preRequest", body);
}
this.debug(
`requesting: ${method} ${path}`,
`payload: ${body ? headers["Content-Type"] : "none"}`
);
this._start = Date.now();
return await this.instance.request({
method,
url: path,
headers,
data: body
}).then((r) => this.handleResponse(r)).catch((e) => this.handleError(e));
}
async raw(method, url, body) {
const headers = this.getHeaders();
if (body !== null && body !== void 0) {
if (typeof body === "string") {
headers["Content-Type"] = "text/plain";
} else {
body = JSON.stringify(body);
}
super.emit("preRequest", body);
}
this.debug(
`requesting: ${method} ${url}`,
`payload: ${body ? headers["Content-Type"] : "none"}`
);
this._start = Date.now();
return await import_axios.default.request({
url,
method,
headers,
data: body
}).then((r) => this.handleResponse(r)).catch((e) => this.handleError(e));
}
handleResponse(res) {
this._ping = Date.now() - this._start;
this.debug(
`received status: ${res.status} (${this._ping}ms)`,
`body: ${res.data ? res.headers["content-type"] : "none"}`
);
if ([202, 204].includes(res.status))
return;
super.emit("postRequest", res.data);
if (res.data.object && res.data.object === "null_resource")
throw new RequestError("Request returned a null resource object");
return res.data;
}
handleError(err) {
this._ping = Date.now() - this._start;
this.debug(
`received error: ${err.name} (${this._ping}ms)`,
`message: ${err.message}`
);
if (err.response === void 0)
throw new RequestError(
`An unknown request error occurred: ${err.message}`
);
if (err.response.status >= 500)
throw new RequestError(
`Received an unexpected response from the API (code ${err.response.status})`
);
throw new PteroAPIError(err.response.data);
}
get(path, params, body, cls) {
const query = params && cls ? buildQuery(params, cls.getQueryOptions()) : "";
return this._make("GET", path + query, body);
}
post(path, body) {
return this._make("POST", path, body);
}
patch(path, body) {
return this._make("PATCH", path, body);
}
put(path, body) {
return this._make("PUT", path, body);
}
delete(path, body) {
return this._make("DELETE", path, body);
}
};
__name(RequestManager, "RequestManager");
// src/structures/Permissions.ts
var Flags = /* @__PURE__ */ ((Flags2) => {
Flags2["WEBSOCKET_CONNECT"] = "websocket.connect";
Flags2["CONTROL_CONSOLE"] = "control.console";
Flags2["CONTROL_START"] = "control.start";
Flags2["CONTROL_STOP"] = "control.stop";
Flags2["CONTROL_RESTART"] = "control.restart";
Flags2["USER_CREATE"] = "user.create";
Flags2["USER_READ"] = "user.read";
Flags2["USER_UPDATE"] = "user.update";
Flags2["USER_DELETE"] = "user.delete";
Flags2["FILE_CREATE"] = "file.create";
Flags2["FILE_READ"] = "file.read";
Flags2["FILE_READ_CONTENT"] = "file.read-content";
Flags2["FILE_UPDATE"] = "file.update";
Flags2["FILE_DELETE"] = "file.delete";
Flags2["FILE_ARCHIVE"] = "file.archive";
Flags2["FILE_SFTP"] = "file.sftp";
Flags2["BACKUP_CREATE"] = "backup.create";
Flags2["BACKUP_READ"] = "backup.read";
Flags2["BACKUP_UPDATE"] = "backup.update";
Flags2["BACKUP_DELETE"] = "backup.delete";
Flags2["ALLOCATION_READ"] = "allocation.read";
Flags2["ALLOCATION_CREATE"] = "allocation.create";
Flags2["ALLOCATION_UPDATE"] = "allocation.update";
Flags2["ALLOCATION_DELETE"] = "allocation.delete";
Flags2["STARTUP_READ"] = "startup.read";
Flags2["STARTUP_UPDATE"] = "startup.update";
Flags2["DATABASE_CREATE"] = "database.create";
Flags2["DATABASE_READ"] = "database.read";
Flags2["DATABASE_UPDATE"] = "database.update";
Flags2["DATABASE_DELETE"] = "database.delete";
Flags2["DATABASE_VIEW_PASSWORD"] = "database.view_password";
Flags2["SCHEDULE_CREATE"] = "schedule.create";
Flags2["SCHEDULE_READ"] = "schedule.read";
Flags2["SCHEDULE_UPDATE"] = "schedule.update";
Flags2["SCHEDULE_DELETE"] = "schedule.delete";
Flags2["SETTINGS_RENAME"] = "settings.rename";
Flags2["SETTINGS_REINSTALL"] = "settings.reinstall";
Flags2["ADMIN_WEBSOCKET_ERRORS"] = "admin.websocket.errors";
Flags2["ADMIN_WEBSOCKET_INSTALL"] = "admin.websocket.install";
Flags2["ADMIN_WEBSOCKET_TRANSFER"] = "admin.websocket.transfer";
return Flags2;
})(Flags || {});
var Permissions = class {
static get CONTROL() {
return Object.freeze([
"control.console" /* CONTROL_CONSOLE */,
"control.start" /* CONTROL_START */,
"control.stop" /* CONTROL_STOP */,
"control.restart" /* CONTROL_RESTART */
]);
}
static get USERS() {
return Object.freeze([
"user.create" /* USER_CREATE */,
"user.read" /* USER_READ */,
"user.update" /* USER_UPDATE */,
"user.delete" /* USER_DELETE */
]);
}
static get FILES() {
return Object.freeze([
"file.create" /* FILE_CREATE */,
"file.read" /* FILE_READ */,
"file.read-content" /* FILE_READ_CONTENT */,
"file.update" /* FILE_UPDATE */,
"file.delete" /* FILE_DELETE */,
"file.archive" /* FILE_ARCHIVE */,
"file.sftp" /* FILE_SFTP */
]);
}
static get BACKUPS() {
return Object.freeze([
"backup.create" /* BACKUP_CREATE */,
"backup.read" /* BACKUP_READ */,
"backup.update" /* BACKUP_UPDATE */,
"backup.delete" /* BACKUP_DELETE */
]);
}
static get ALLOCATIONS() {
return Object.freeze([
"allocation.read" /* ALLOCATION_READ */,
"allocation.create" /* ALLOCATION_CREATE */,
"allocation.update" /* ALLOCATION_UPDATE */,
"allocation.delete" /* ALLOCATION_DELETE */
]);
}
static get STARTUPS() {
return Object.freeze(["startup.read" /* STARTUP_READ */, "startup.update" /* STARTUP_UPDATE */]);
}
static get DATABASES() {
return Object.freeze([
"database.create" /* DATABASE_CREATE */,
"database.read" /* DATABASE_READ */,
"database.update" /* DATABASE_UPDATE */,
"database.delete" /* DATABASE_DELETE */,
"database.view_password" /* DATABASE_VIEW_PASSWORD */
]);
}
static get SCHEDULES() {
return Object.freeze([
"schedule.create" /* SCHEDULE_CREATE */,
"schedule.read" /* SCHEDULE_READ */,
"schedule.update" /* SCHEDULE_UPDATE */,
"schedule.delete" /* SCHEDULE_DELETE */
]);
}
static get SETTINGS() {
return Object.freeze(["settings.rename" /* SETTINGS_RENAME */, "settings.reinstall" /* SETTINGS_REINSTALL */]);
}
static get ADMIN() {
return Object.freeze([
"admin.websocket.errors" /* ADMIN_WEBSOCKET_ERRORS */,
"admin.websocket.install" /* ADMIN_WEBSOCKET_INSTALL */,
"admin.websocket.transfer" /* ADMIN_WEBSOCKET_TRANSFER */
]);
}
constructor(...perms) {
this.value = Permissions.resolve(...perms);
}
static resolve(...perms) {
const res = [];
const values = Object.values(Flags);
if (perms.some((p) => p === "*"))
return values;
for (const p of perms) {
if (p in Flags || values.includes(p)) {
res.push(p);
} else {
throw new Error(`unknown permission '${p}'`);
}
}
return res;
}
hasAny(...perms) {
const res = Permissions.resolve(...perms);
return res.some((p) => this.value.includes(p));
}
hasAll(...perms) {
const res = Permissions.resolve(...perms);
return res.every((p) => this.value.includes(p));
}
isAdmin() {
return this.value.some(
(p) => [
"admin.websocket.errors" /* ADMIN_WEBSOCKET_ERRORS */,
"admin.websocket.install" /* ADMIN_WEBSOCKET_INSTALL */,
"admin.websocket.transfer" /* ADMIN_WEBSOCKET_TRANSFER */
].includes(p)
);
}
add(...perms) {
this.value = this.value.concat(Permissions.resolve(...perms));
return this;
}
remove(...perms) {
const res = Permissions.resolve(...perms);
this.value = this.value.filter((p) => !res.includes(p));
return this;
}
serialize() {
const res = {};
for (let [k, v] of Object.entries(Flags))
res[k] = this.value.includes(v);
return res;
}
};
__name(Permissions, "Permissions");
// sr