mirror of
https://github.com/vyme-fr/MercuryCloud_Dashboard.git
synced 2026-01-19 00:57:23 +01:00
234 lines
8.3 KiB
JavaScript
234 lines
8.3 KiB
JavaScript
const Node = require('../structures/Node');
|
|
const Dict = require('../structures/Dict');
|
|
const build = require('../util/query');
|
|
const endpoints = require('./endpoints');
|
|
|
|
class NodeManager {
|
|
/**
|
|
* Allowed filter arguments for nodes.
|
|
*/
|
|
static get FILTERS() {
|
|
return Object.freeze(['uuid', 'name', 'fqdn', 'daemon_token_id']);
|
|
}
|
|
|
|
/**
|
|
* Allowed include arguments for nodes.
|
|
*/
|
|
static get INCLUDES() {
|
|
return Object.freeze(['allocations', 'location', 'servers']);
|
|
}
|
|
|
|
/**
|
|
* Allowed sort arguments for nodes.
|
|
*/
|
|
static get SORTS() {
|
|
return Object.freeze(['id', 'uuid', 'memory', 'disk']);
|
|
}
|
|
|
|
constructor(client) {
|
|
this.client = client;
|
|
|
|
/** @type {Dict<number, Node>} */
|
|
this.cache = new Dict();
|
|
}
|
|
|
|
_patch(data) {
|
|
if (data.data) {
|
|
const res = new Dict();
|
|
for (const o of data.data) {
|
|
const n = new Node(this.client, o);
|
|
res.set(n.id, n);
|
|
}
|
|
|
|
if (this.client.options.nodes.cache) res.forEach((v, k) => this.cache.set(k, v));
|
|
return res;
|
|
}
|
|
|
|
const n = new Node(this.client, data);
|
|
if (this.client.options.nodes.cache) this.cache.set(n.id, n);
|
|
return n;
|
|
}
|
|
|
|
/**
|
|
* Resolves a node from an object. This can be:
|
|
* * a string
|
|
* * a number
|
|
* * an object
|
|
*
|
|
* Returns `undefined` if not found.
|
|
* @param {string|number|object|Node} obj The object to resolve from.
|
|
* @returns {?Node} The resolved node.
|
|
*/
|
|
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 undefined;
|
|
}
|
|
|
|
/**
|
|
* Returns a formatted URL to the node in the admin panel.
|
|
* @param {number|Node} node The node or ID of the node.
|
|
* @returns {string} The formatted URL.
|
|
*/
|
|
adminURLFor(node) {
|
|
if (node instanceof Node) return node.adminURL;
|
|
return `${this.client.domain}/admin/nodes/view/${node}`;
|
|
}
|
|
|
|
/**
|
|
* Fetches a node from the Pterodactyl API with an optional cache check.
|
|
* @param {number} [id] The ID of the node.
|
|
* @param {object} [options] Additional fetch options.
|
|
* @param {boolean} [options.force] Whether to skip checking the cache and fetch directly.
|
|
* @param {string[]} [options.include] Additional data to include about the node.
|
|
* @returns {Promise<Node|Dict<number, Node>>} The fetched node(s).
|
|
*/
|
|
async fetch(id, options = {}) {
|
|
if (id && !options.force) {
|
|
const n = this.cache.get(id);
|
|
if (n) return Promise.resolve(s);
|
|
}
|
|
|
|
const query = build(options, { include: NodeManager.INCLUDES });
|
|
const data = await this.client.requests.get(
|
|
(id ? endpoints.nodes.get(id) : endpoints.nodes.main) + query
|
|
);
|
|
return this._patch(data);
|
|
}
|
|
|
|
/**
|
|
* Queries the API for a node (or nodes) that match the specified query filter/sort.
|
|
* This does NOT check the cache first, it is a direct fetch from the API.
|
|
* Available filters:
|
|
* * uuid
|
|
* * name
|
|
* * fqdn
|
|
* * daemonTokenId
|
|
*
|
|
* Available sort options:
|
|
* * id
|
|
* * -id
|
|
* * uuid
|
|
* * -uuid
|
|
* * memory
|
|
* * -memory
|
|
* * disk
|
|
* * -disk
|
|
*
|
|
* @param {string} entity The entity to query.
|
|
* @param {string} filter The filter to use for the query.
|
|
* @param {string} sort The order to sort the results in.
|
|
* @returns {Promise<Dict<number, Node>>} A dict of the quiried nodes.
|
|
*/
|
|
async query(entity, filter, sort) {
|
|
if (!sort && !filter) throw new Error('Sort or filter is required.');
|
|
if (filter === 'daemonTokenId') filter = 'daemon_token_id';
|
|
|
|
const { FILTERS, SORTS } = NodeManager;
|
|
const query = build(
|
|
{ filter:[filter, entity], sort },
|
|
{ filters: FILTERS, sorts: SORTS }
|
|
);
|
|
|
|
const data = await this.client.requests.get(endpoints.nodes.main + query);
|
|
return this._patch(data);
|
|
}
|
|
|
|
/**
|
|
* Creates a new Pterodactyl server node.
|
|
* @param {object} options Node creation options.
|
|
* @param {string} options.name The name of the node.
|
|
* @param {number} options.location The ID of the location for the node.
|
|
* @param {string} options.fqdn The FQDN for the node.
|
|
* @param {string} options.scheme The HTTP/HTTPS scheme for the node.
|
|
* @param {number} options.memory The amount of memory for the node.
|
|
* @param {number} options.disk The amount of disk for the node.
|
|
* @param {object} options.sftp SFTP options.
|
|
* @param {number} options.sftp.port The port for the SFTP.
|
|
* @param {number} options.sftp.listener The listener port for the SFTP.
|
|
* @param {number} [options.upload_size] The maximum upload size for the node.
|
|
* @param {number} [options.memory_overallocate] The amount of memory over allocation.
|
|
* @param {number} [options.disk_overallocate] The amount of disk over allocation.
|
|
* @returns {Promise<Node>} The new node.
|
|
*/
|
|
async create(options = {}) {
|
|
if (
|
|
!options.name ||
|
|
!options.location ||
|
|
!options.fqdn ||
|
|
!options.scheme ||
|
|
!options.memory ||
|
|
!options.disk ||
|
|
!options.sftp?.port ||
|
|
!options.sftp?.listener
|
|
) throw new Error('Missing required Node creation option.');
|
|
|
|
const payload = {};
|
|
payload.name = options.name;
|
|
payload.location = options.location;
|
|
payload.fqdn = options.fqdn;
|
|
payload.scheme = options.scheme;
|
|
payload.memory = options.memory;
|
|
payload.disk = options.disk;
|
|
payload.sftp = options.sftp;
|
|
payload.upload_size = options.upload_size ?? 100;
|
|
payload.memory_overallocate = options.memory_overallocate ?? 0;
|
|
payload.disk_overallocate = options.disk_overallocate ?? 0;
|
|
|
|
const data = await this.client.requests.post(
|
|
endpoints.nodes.main, payload
|
|
);
|
|
return this._patch(data);
|
|
}
|
|
|
|
/**
|
|
* Updates a specified node.
|
|
* @param {number|Node} node The node to update.
|
|
* @param {object} options Node update options.
|
|
* @param {string} [options.name] The name of the node.
|
|
* @param {number} [options.location] The ID of the location for the node.
|
|
* @param {string} [options.fqdn] The FQDN for the node.
|
|
* @param {string} [options.scheme] The HTTP/HTTPS scheme for the node.
|
|
* @param {number} [options.memory] The amount of memory for the node.
|
|
* @param {number} [options.disk] The amount of disk for the node.
|
|
* @param {object} [options.sftp] SFTP options.
|
|
* @param {number} [options.sftp.port] The port for the SFTP.
|
|
* @param {number} [options.sftp.listener] The listener port for the SFTP.
|
|
* @param {number} [options.upload_size] The maximum upload size for the node.
|
|
* @param {number} [options.memory_overallocate] The amount of memory over allocation.
|
|
* @param {number} [options.disk_overallocate] The amount of disk over allocation.
|
|
* @returns {Promise<Node>} The updated node instance.
|
|
*/
|
|
async update(node, options = {}) {
|
|
if (typeof node === 'number') node = await this.fetch(node);
|
|
if (!Object.keys(options).length) throw new Error('Too few options to update.');
|
|
|
|
const { id } = node;
|
|
const payload = {};
|
|
Object.entries(node.toJSON()).forEach(e => payload[e[0]] = options[e[0]] ?? e[1]);
|
|
payload.memory_overallocate = payload.overallocated_memory;
|
|
payload.disk_overallocate = payload.overallocated_disk;
|
|
|
|
const data = await this.client.requests.patch(
|
|
endpoints.nodes.get(id), payload
|
|
);
|
|
return this._patch(data);
|
|
}
|
|
|
|
/**
|
|
* Deletes a node from Pterodactyl.
|
|
* @param {number|Node} node The node to delete.
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async delete(node) {
|
|
if (node instanceof Node) node = node.id;
|
|
await this.client.requests.delete(endpoints.nodes.get(node));
|
|
this.cache.delete(node);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
module.exports = NodeManager;
|