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