@ho3einwave/pterodactyl-ts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/index.d.mts +1069 -0
- package/dist/index.mjs +911 -0
- package/package.json +49 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
//#region src/core/errors.ts
|
|
2
|
+
/** Base error for all Pterodactyl API errors. */
|
|
3
|
+
var PteroError = class extends Error {
|
|
4
|
+
/** HTTP status code. */
|
|
5
|
+
status;
|
|
6
|
+
/** Machine-readable error code from the API. */
|
|
7
|
+
code;
|
|
8
|
+
/** Raw error objects from the API response. */
|
|
9
|
+
errors;
|
|
10
|
+
constructor(status, errors) {
|
|
11
|
+
const first = errors[0];
|
|
12
|
+
super(first?.detail ?? `API error ${status}`);
|
|
13
|
+
this.name = "PteroError";
|
|
14
|
+
this.status = status;
|
|
15
|
+
this.code = first?.code ?? "UnknownError";
|
|
16
|
+
this.errors = errors;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
/** Thrown on 422 validation errors. Includes per-field error details. */
|
|
20
|
+
var PteroValidationError = class extends PteroError {
|
|
21
|
+
/** Map of field name to error messages. */
|
|
22
|
+
fieldErrors;
|
|
23
|
+
constructor(errors) {
|
|
24
|
+
super(422, errors);
|
|
25
|
+
this.name = "PteroValidationError";
|
|
26
|
+
this.fieldErrors = {};
|
|
27
|
+
for (const err of errors) if (err.source?.field) {
|
|
28
|
+
const field = err.source.field;
|
|
29
|
+
if (!this.fieldErrors[field]) this.fieldErrors[field] = [];
|
|
30
|
+
this.fieldErrors[field].push(err.detail);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/** Thrown on 429 rate limit errors. Includes retry timing info. */
|
|
35
|
+
var PteroRateLimitError = class extends PteroError {
|
|
36
|
+
/** Seconds to wait before retrying (from Retry-After header). */
|
|
37
|
+
retryAfter;
|
|
38
|
+
constructor(errors, retryAfter) {
|
|
39
|
+
super(429, errors);
|
|
40
|
+
this.name = "PteroRateLimitError";
|
|
41
|
+
this.retryAfter = retryAfter;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/core/http-client.ts
|
|
47
|
+
var HttpClient = class {
|
|
48
|
+
baseUrl;
|
|
49
|
+
apiKey;
|
|
50
|
+
_rateLimit = null;
|
|
51
|
+
constructor(options) {
|
|
52
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
53
|
+
this.apiKey = options.apiKey;
|
|
54
|
+
}
|
|
55
|
+
/** Current rate limit info from the last response, or null if no request has been made. */
|
|
56
|
+
get rateLimit() {
|
|
57
|
+
return this._rateLimit;
|
|
58
|
+
}
|
|
59
|
+
/** Make a GET request and unwrap a single object envelope. */
|
|
60
|
+
async get(path, options) {
|
|
61
|
+
return (await (await this.request("GET", path, void 0, options)).json()).attributes;
|
|
62
|
+
}
|
|
63
|
+
/** Make a GET request and unwrap a list envelope with pagination. */
|
|
64
|
+
async getList(path, options) {
|
|
65
|
+
const json = await (await this.request("GET", path, void 0, options)).json();
|
|
66
|
+
return this.unwrapList(json);
|
|
67
|
+
}
|
|
68
|
+
/** Make a POST request and unwrap a single object envelope. */
|
|
69
|
+
async post(path, body, options) {
|
|
70
|
+
const response = await this.request("POST", path, body, options);
|
|
71
|
+
if (response.status === 204) return;
|
|
72
|
+
return (await response.json()).attributes;
|
|
73
|
+
}
|
|
74
|
+
/** Make a PUT request and unwrap a single object envelope. */
|
|
75
|
+
async put(path, body, options) {
|
|
76
|
+
const response = await this.request("PUT", path, body, options);
|
|
77
|
+
if (response.status === 204) return;
|
|
78
|
+
return (await response.json()).attributes;
|
|
79
|
+
}
|
|
80
|
+
/** Make a PATCH request and unwrap a single object envelope. */
|
|
81
|
+
async patch(path, body, options) {
|
|
82
|
+
const response = await this.request("PATCH", path, body, options);
|
|
83
|
+
if (response.status === 204) return;
|
|
84
|
+
return (await response.json()).attributes;
|
|
85
|
+
}
|
|
86
|
+
/** Make a DELETE request. Returns void (expects 204). */
|
|
87
|
+
async delete(path, body, options) {
|
|
88
|
+
await this.request("DELETE", path, body, options);
|
|
89
|
+
}
|
|
90
|
+
/** Make a raw request and return the Response (for non-JSON endpoints like file downloads). */
|
|
91
|
+
async raw(method, path, body, options) {
|
|
92
|
+
return this.request(method, path, body, options);
|
|
93
|
+
}
|
|
94
|
+
/** Make a request with a raw text body (Content-Type: text/plain). */
|
|
95
|
+
async postText(path, text, options) {
|
|
96
|
+
const url = this.buildUrl(path, options);
|
|
97
|
+
const response = await fetch(url, {
|
|
98
|
+
method: "POST",
|
|
99
|
+
headers: {
|
|
100
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
101
|
+
Accept: "Application/vnd.pterodactyl.v1+json",
|
|
102
|
+
"Content-Type": "text/plain"
|
|
103
|
+
},
|
|
104
|
+
body: text
|
|
105
|
+
});
|
|
106
|
+
this.trackRateLimit(response);
|
|
107
|
+
if (!response.ok) await this.handleError(response);
|
|
108
|
+
}
|
|
109
|
+
async request(method, path, body, options) {
|
|
110
|
+
const url = this.buildUrl(path, options);
|
|
111
|
+
const headers = {
|
|
112
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
113
|
+
Accept: "Application/vnd.pterodactyl.v1+json"
|
|
114
|
+
};
|
|
115
|
+
const init = {
|
|
116
|
+
method,
|
|
117
|
+
headers
|
|
118
|
+
};
|
|
119
|
+
if (body !== void 0) {
|
|
120
|
+
headers["Content-Type"] = "application/json";
|
|
121
|
+
init.body = JSON.stringify(body);
|
|
122
|
+
}
|
|
123
|
+
const response = await fetch(url, init);
|
|
124
|
+
this.trackRateLimit(response);
|
|
125
|
+
if (!response.ok) await this.handleError(response);
|
|
126
|
+
return response;
|
|
127
|
+
}
|
|
128
|
+
buildUrl(path, options) {
|
|
129
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
130
|
+
if (!options) return url.toString();
|
|
131
|
+
if (options.filters) for (const [key, value] of Object.entries(options.filters)) url.searchParams.set(`filter[${key}]`, value);
|
|
132
|
+
if (options.sort) url.searchParams.set("sort", options.sort);
|
|
133
|
+
if (options.include?.length) url.searchParams.set("include", options.include.join(","));
|
|
134
|
+
if (options.page !== void 0) url.searchParams.set("page", String(options.page));
|
|
135
|
+
if (options.perPage !== void 0) url.searchParams.set("per_page", String(options.perPage));
|
|
136
|
+
return url.toString();
|
|
137
|
+
}
|
|
138
|
+
trackRateLimit(response) {
|
|
139
|
+
const limit = response.headers.get("X-RateLimit-Limit");
|
|
140
|
+
const remaining = response.headers.get("X-RateLimit-Remaining");
|
|
141
|
+
const reset = response.headers.get("X-RateLimit-Reset");
|
|
142
|
+
if (limit && remaining && reset) this._rateLimit = {
|
|
143
|
+
limit: Number(limit),
|
|
144
|
+
remaining: Number(remaining),
|
|
145
|
+
reset: Number(reset)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async handleError(response) {
|
|
149
|
+
let errors;
|
|
150
|
+
try {
|
|
151
|
+
errors = (await response.json()).errors;
|
|
152
|
+
} catch {
|
|
153
|
+
errors = [{
|
|
154
|
+
code: "UnknownError",
|
|
155
|
+
status: String(response.status),
|
|
156
|
+
detail: response.statusText || `HTTP ${response.status}`
|
|
157
|
+
}];
|
|
158
|
+
}
|
|
159
|
+
if (response.status === 422) throw new PteroValidationError(errors);
|
|
160
|
+
if (response.status === 429) {
|
|
161
|
+
const retryAfter = Number(response.headers.get("Retry-After") ?? "60");
|
|
162
|
+
throw new PteroRateLimitError(errors, retryAfter);
|
|
163
|
+
}
|
|
164
|
+
throw new PteroError(response.status, errors);
|
|
165
|
+
}
|
|
166
|
+
unwrapList(raw) {
|
|
167
|
+
const data = raw.data.map((item) => item.attributes);
|
|
168
|
+
return {
|
|
169
|
+
data,
|
|
170
|
+
pagination: raw.meta?.pagination ? {
|
|
171
|
+
total: raw.meta.pagination.total,
|
|
172
|
+
count: raw.meta.pagination.count,
|
|
173
|
+
perPage: raw.meta.pagination.per_page,
|
|
174
|
+
currentPage: raw.meta.pagination.current_page,
|
|
175
|
+
totalPages: raw.meta.pagination.total_pages
|
|
176
|
+
} : {
|
|
177
|
+
total: data.length,
|
|
178
|
+
count: data.length,
|
|
179
|
+
perPage: data.length,
|
|
180
|
+
currentPage: 1,
|
|
181
|
+
totalPages: 1
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/client/account-manager.ts
|
|
189
|
+
const BASE$6 = "/api/client/account";
|
|
190
|
+
var AccountManager = class {
|
|
191
|
+
constructor(http) {
|
|
192
|
+
this.http = http;
|
|
193
|
+
}
|
|
194
|
+
async getDetails() {
|
|
195
|
+
return this.http.get(BASE$6);
|
|
196
|
+
}
|
|
197
|
+
async get2FASetup() {
|
|
198
|
+
return (await (await this.http.raw("GET", `${BASE$6}/two-factor`)).json()).data;
|
|
199
|
+
}
|
|
200
|
+
async enable2FA(code) {
|
|
201
|
+
return this.http.post(`${BASE$6}/two-factor`, { code });
|
|
202
|
+
}
|
|
203
|
+
async disable2FA(password) {
|
|
204
|
+
await this.http.post(`${BASE$6}/two-factor/disable`, { password });
|
|
205
|
+
}
|
|
206
|
+
async updateEmail(email, password) {
|
|
207
|
+
await this.http.put(`${BASE$6}/email`, {
|
|
208
|
+
email,
|
|
209
|
+
password
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
async updatePassword(currentPassword, password, passwordConfirmation) {
|
|
213
|
+
await this.http.put(`${BASE$6}/password`, {
|
|
214
|
+
current_password: currentPassword,
|
|
215
|
+
password,
|
|
216
|
+
password_confirmation: passwordConfirmation
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async listApiKeys() {
|
|
220
|
+
return (await this.http.getList(`${BASE$6}/api-keys`)).data;
|
|
221
|
+
}
|
|
222
|
+
async createApiKey(description, allowedIps) {
|
|
223
|
+
const json = await (await this.http.raw("POST", `${BASE$6}/api-keys`, {
|
|
224
|
+
description,
|
|
225
|
+
allowed_ips: allowedIps ?? []
|
|
226
|
+
})).json();
|
|
227
|
+
return {
|
|
228
|
+
...json.attributes,
|
|
229
|
+
secret_token: json.meta.secret_token
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
async deleteApiKey(identifier) {
|
|
233
|
+
await this.http.delete(`${BASE$6}/api-keys/${identifier}`);
|
|
234
|
+
}
|
|
235
|
+
async listSSHKeys() {
|
|
236
|
+
return (await this.http.getList(`${BASE$6}/ssh-keys`)).data;
|
|
237
|
+
}
|
|
238
|
+
async createSSHKey(name, publicKey) {
|
|
239
|
+
return this.http.post(`${BASE$6}/ssh-keys`, {
|
|
240
|
+
name,
|
|
241
|
+
public_key: publicKey
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
async deleteSSHKey(fingerprint) {
|
|
245
|
+
await this.http.post(`${BASE$6}/ssh-keys/remove`, { fingerprint });
|
|
246
|
+
}
|
|
247
|
+
async getActivity(options) {
|
|
248
|
+
return this.http.getList(`${BASE$6}/activity`, options);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
//#endregion
|
|
253
|
+
//#region src/client/server/backup-manager.ts
|
|
254
|
+
var BackupManager = class {
|
|
255
|
+
base;
|
|
256
|
+
constructor(http, serverId) {
|
|
257
|
+
this.http = http;
|
|
258
|
+
this.base = `/api/client/servers/${serverId}/backups`;
|
|
259
|
+
}
|
|
260
|
+
async list(options) {
|
|
261
|
+
return this.http.getList(this.base, options);
|
|
262
|
+
}
|
|
263
|
+
async get(backupId) {
|
|
264
|
+
return this.http.get(`${this.base}/${backupId}`);
|
|
265
|
+
}
|
|
266
|
+
async create(params) {
|
|
267
|
+
return this.http.post(this.base, params);
|
|
268
|
+
}
|
|
269
|
+
async getDownloadUrl(backupId) {
|
|
270
|
+
return (await this.http.get(`${this.base}/${backupId}/download`)).url;
|
|
271
|
+
}
|
|
272
|
+
async delete(backupId) {
|
|
273
|
+
await this.http.delete(`${this.base}/${backupId}`);
|
|
274
|
+
}
|
|
275
|
+
async restore(backupId) {
|
|
276
|
+
await this.http.post(`${this.base}/${backupId}/restore`);
|
|
277
|
+
}
|
|
278
|
+
async toggleLock(backupId) {
|
|
279
|
+
await this.http.post(`${this.base}/${backupId}/lock`);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/client/server/database-manager.ts
|
|
285
|
+
var DatabaseManager = class {
|
|
286
|
+
base;
|
|
287
|
+
constructor(http, serverId) {
|
|
288
|
+
this.http = http;
|
|
289
|
+
this.base = `/api/client/servers/${serverId}/databases`;
|
|
290
|
+
}
|
|
291
|
+
async list() {
|
|
292
|
+
return (await this.http.getList(this.base)).data;
|
|
293
|
+
}
|
|
294
|
+
async create(params) {
|
|
295
|
+
return this.http.post(this.base, params);
|
|
296
|
+
}
|
|
297
|
+
async rotatePassword(databaseId) {
|
|
298
|
+
return this.http.post(`${this.base}/${databaseId}/rotate-password`);
|
|
299
|
+
}
|
|
300
|
+
async delete(databaseId) {
|
|
301
|
+
await this.http.delete(`${this.base}/${databaseId}`);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
//#endregion
|
|
306
|
+
//#region src/client/server/file-manager.ts
|
|
307
|
+
var FileManager = class {
|
|
308
|
+
base;
|
|
309
|
+
constructor(http, serverId) {
|
|
310
|
+
this.http = http;
|
|
311
|
+
this.base = `/api/client/servers/${serverId}/files`;
|
|
312
|
+
}
|
|
313
|
+
async list(directory = "/") {
|
|
314
|
+
return (await this.http.getList(`${this.base}/list`, { filters: { directory } })).data;
|
|
315
|
+
}
|
|
316
|
+
async getContent(file) {
|
|
317
|
+
const path = `${this.base}/contents?file=${encodeURIComponent(file)}`;
|
|
318
|
+
return (await this.http.raw("GET", path)).text();
|
|
319
|
+
}
|
|
320
|
+
async writeFile(file, content) {
|
|
321
|
+
const path = `${this.base}/write?file=${encodeURIComponent(file)}`;
|
|
322
|
+
await this.http.postText(path, content);
|
|
323
|
+
}
|
|
324
|
+
async getUploadUrl(directory = "/") {
|
|
325
|
+
const path = `${this.base}/upload?directory=${encodeURIComponent(directory)}`;
|
|
326
|
+
return (await this.http.get(path)).url;
|
|
327
|
+
}
|
|
328
|
+
async getDownloadUrl(file) {
|
|
329
|
+
const path = `${this.base}/download?file=${encodeURIComponent(file)}`;
|
|
330
|
+
return (await this.http.get(path)).url;
|
|
331
|
+
}
|
|
332
|
+
async createFolder(root, name) {
|
|
333
|
+
await this.http.post(`${this.base}/create-folder`, {
|
|
334
|
+
root,
|
|
335
|
+
name
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async copy(location) {
|
|
339
|
+
await this.http.post(`${this.base}/copy`, { location });
|
|
340
|
+
}
|
|
341
|
+
async rename(root, files) {
|
|
342
|
+
await this.http.put(`${this.base}/rename`, {
|
|
343
|
+
root,
|
|
344
|
+
files
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
async delete(root, files) {
|
|
348
|
+
await this.http.post(`${this.base}/delete`, {
|
|
349
|
+
root,
|
|
350
|
+
files
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async compress(root, files) {
|
|
354
|
+
return this.http.post(`${this.base}/compress`, {
|
|
355
|
+
root,
|
|
356
|
+
files
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
async decompress(root, file) {
|
|
360
|
+
await this.http.post(`${this.base}/decompress`, {
|
|
361
|
+
root,
|
|
362
|
+
file
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
async chmod(root, files) {
|
|
366
|
+
await this.http.post(`${this.base}/chmod`, {
|
|
367
|
+
root,
|
|
368
|
+
files
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
async pull(url, directory, filename) {
|
|
372
|
+
await this.http.post(`${this.base}/pull`, {
|
|
373
|
+
url,
|
|
374
|
+
directory,
|
|
375
|
+
...filename && { filename }
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
//#endregion
|
|
381
|
+
//#region src/client/server/network-manager.ts
|
|
382
|
+
var NetworkManager = class {
|
|
383
|
+
base;
|
|
384
|
+
constructor(http, serverId) {
|
|
385
|
+
this.http = http;
|
|
386
|
+
this.base = `/api/client/servers/${serverId}/network/allocations`;
|
|
387
|
+
}
|
|
388
|
+
async list() {
|
|
389
|
+
return (await this.http.getList(this.base)).data;
|
|
390
|
+
}
|
|
391
|
+
async assign() {
|
|
392
|
+
return this.http.post(this.base);
|
|
393
|
+
}
|
|
394
|
+
async setPrimary(allocationId) {
|
|
395
|
+
return this.http.post(`${this.base}/${allocationId}/primary`);
|
|
396
|
+
}
|
|
397
|
+
async updateNotes(allocationId, notes) {
|
|
398
|
+
return this.http.post(`${this.base}/${allocationId}`, { notes });
|
|
399
|
+
}
|
|
400
|
+
async remove(allocationId) {
|
|
401
|
+
await this.http.delete(`${this.base}/${allocationId}`);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/client/server/schedule-manager.ts
|
|
407
|
+
var ScheduleManager = class {
|
|
408
|
+
base;
|
|
409
|
+
constructor(http, serverId) {
|
|
410
|
+
this.http = http;
|
|
411
|
+
this.base = `/api/client/servers/${serverId}/schedules`;
|
|
412
|
+
}
|
|
413
|
+
async list() {
|
|
414
|
+
return (await this.http.getList(this.base)).data;
|
|
415
|
+
}
|
|
416
|
+
async get(scheduleId) {
|
|
417
|
+
return this.http.get(`${this.base}/${scheduleId}`);
|
|
418
|
+
}
|
|
419
|
+
async create(params) {
|
|
420
|
+
return this.http.post(this.base, params);
|
|
421
|
+
}
|
|
422
|
+
async update(scheduleId, params) {
|
|
423
|
+
await this.http.post(`${this.base}/${scheduleId}`, params);
|
|
424
|
+
}
|
|
425
|
+
async delete(scheduleId) {
|
|
426
|
+
await this.http.delete(`${this.base}/${scheduleId}`);
|
|
427
|
+
}
|
|
428
|
+
async execute(scheduleId) {
|
|
429
|
+
await this.http.post(`${this.base}/${scheduleId}/execute`);
|
|
430
|
+
}
|
|
431
|
+
async createTask(scheduleId, params) {
|
|
432
|
+
return this.http.post(`${this.base}/${scheduleId}/tasks`, params);
|
|
433
|
+
}
|
|
434
|
+
async updateTask(scheduleId, taskId, params) {
|
|
435
|
+
return this.http.post(`${this.base}/${scheduleId}/tasks/${taskId}`, params);
|
|
436
|
+
}
|
|
437
|
+
async deleteTask(scheduleId, taskId) {
|
|
438
|
+
await this.http.delete(`${this.base}/${scheduleId}/tasks/${taskId}`);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
//#endregion
|
|
443
|
+
//#region src/client/server/subuser-manager.ts
|
|
444
|
+
var SubuserManager = class {
|
|
445
|
+
base;
|
|
446
|
+
constructor(http, serverId) {
|
|
447
|
+
this.http = http;
|
|
448
|
+
this.base = `/api/client/servers/${serverId}/users`;
|
|
449
|
+
}
|
|
450
|
+
async list() {
|
|
451
|
+
return (await this.http.getList(this.base)).data;
|
|
452
|
+
}
|
|
453
|
+
async get(userId) {
|
|
454
|
+
return this.http.get(`${this.base}/${userId}`);
|
|
455
|
+
}
|
|
456
|
+
async create(params) {
|
|
457
|
+
return this.http.post(this.base, params);
|
|
458
|
+
}
|
|
459
|
+
async update(userId, params) {
|
|
460
|
+
return this.http.post(`${this.base}/${userId}`, params);
|
|
461
|
+
}
|
|
462
|
+
async remove(userId) {
|
|
463
|
+
await this.http.delete(`${this.base}/${userId}`);
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/client/server/server-context.ts
|
|
469
|
+
var ServerContext = class {
|
|
470
|
+
files;
|
|
471
|
+
databases;
|
|
472
|
+
backups;
|
|
473
|
+
schedules;
|
|
474
|
+
network;
|
|
475
|
+
subusers;
|
|
476
|
+
base;
|
|
477
|
+
constructor(http, serverId) {
|
|
478
|
+
this.http = http;
|
|
479
|
+
this.base = `/api/client/servers/${serverId}`;
|
|
480
|
+
this.files = new FileManager(http, serverId);
|
|
481
|
+
this.databases = new DatabaseManager(http, serverId);
|
|
482
|
+
this.backups = new BackupManager(http, serverId);
|
|
483
|
+
this.schedules = new ScheduleManager(http, serverId);
|
|
484
|
+
this.network = new NetworkManager(http, serverId);
|
|
485
|
+
this.subusers = new SubuserManager(http, serverId);
|
|
486
|
+
}
|
|
487
|
+
async getDetails(options) {
|
|
488
|
+
return this.http.get(this.base, options);
|
|
489
|
+
}
|
|
490
|
+
async getResources() {
|
|
491
|
+
return this.http.get(`${this.base}/resources`);
|
|
492
|
+
}
|
|
493
|
+
async sendCommand(command) {
|
|
494
|
+
await this.http.post(`${this.base}/command`, { command });
|
|
495
|
+
}
|
|
496
|
+
async setPowerState(signal) {
|
|
497
|
+
await this.http.post(`${this.base}/power`, { signal });
|
|
498
|
+
}
|
|
499
|
+
async getWebSocketCredentials() {
|
|
500
|
+
return this.http.get(`${this.base}/websocket`);
|
|
501
|
+
}
|
|
502
|
+
async listStartupVariables() {
|
|
503
|
+
return (await this.http.getList(`${this.base}/startup`)).data;
|
|
504
|
+
}
|
|
505
|
+
async updateStartupVariable(key, value) {
|
|
506
|
+
return this.http.put(`${this.base}/startup/variable`, {
|
|
507
|
+
key,
|
|
508
|
+
value
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
async rename(name) {
|
|
512
|
+
await this.http.post(`${this.base}/settings/rename`, { name });
|
|
513
|
+
}
|
|
514
|
+
async reinstall() {
|
|
515
|
+
await this.http.post(`${this.base}/settings/reinstall`);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
//#endregion
|
|
520
|
+
//#region src/client/servers-manager.ts
|
|
521
|
+
const BASE$5 = "/api/client";
|
|
522
|
+
var ServersManager = class {
|
|
523
|
+
constructor(http) {
|
|
524
|
+
this.http = http;
|
|
525
|
+
}
|
|
526
|
+
async list(options) {
|
|
527
|
+
return this.http.getList(`${BASE$5}`, options);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/client/index.ts
|
|
533
|
+
var PteroClient = class {
|
|
534
|
+
account;
|
|
535
|
+
servers;
|
|
536
|
+
http;
|
|
537
|
+
constructor(options) {
|
|
538
|
+
this.http = new HttpClient(options);
|
|
539
|
+
this.account = new AccountManager(this.http);
|
|
540
|
+
this.servers = new ServersManager(this.http);
|
|
541
|
+
}
|
|
542
|
+
/** Create a server context scoped to a specific server identifier. */
|
|
543
|
+
server(serverId) {
|
|
544
|
+
return new ServerContext(this.http, serverId);
|
|
545
|
+
}
|
|
546
|
+
/** Current rate limit info from the last API response. */
|
|
547
|
+
get rateLimit() {
|
|
548
|
+
return this.http.rateLimit;
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
//#endregion
|
|
553
|
+
//#region src/application/location-manager.ts
|
|
554
|
+
const BASE$4 = "/api/application/locations";
|
|
555
|
+
var LocationManager = class {
|
|
556
|
+
constructor(http) {
|
|
557
|
+
this.http = http;
|
|
558
|
+
}
|
|
559
|
+
async list(options) {
|
|
560
|
+
return this.http.getList(BASE$4, options);
|
|
561
|
+
}
|
|
562
|
+
async get(locationId, options) {
|
|
563
|
+
return this.http.get(`${BASE$4}/${locationId}`, options);
|
|
564
|
+
}
|
|
565
|
+
async create(params) {
|
|
566
|
+
return this.http.post(BASE$4, params);
|
|
567
|
+
}
|
|
568
|
+
async update(locationId, params) {
|
|
569
|
+
return this.http.patch(`${BASE$4}/${locationId}`, params);
|
|
570
|
+
}
|
|
571
|
+
async delete(locationId) {
|
|
572
|
+
await this.http.delete(`${BASE$4}/${locationId}`);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
//#endregion
|
|
577
|
+
//#region src/application/nest-manager.ts
|
|
578
|
+
const BASE$3 = "/api/application/nests";
|
|
579
|
+
var NestManager = class {
|
|
580
|
+
constructor(http) {
|
|
581
|
+
this.http = http;
|
|
582
|
+
}
|
|
583
|
+
async list(options) {
|
|
584
|
+
return this.http.getList(BASE$3, options);
|
|
585
|
+
}
|
|
586
|
+
async get(nestId, options) {
|
|
587
|
+
return this.http.get(`${BASE$3}/${nestId}`, options);
|
|
588
|
+
}
|
|
589
|
+
async listEggs(nestId, options) {
|
|
590
|
+
return this.http.getList(`${BASE$3}/${nestId}/eggs`, options);
|
|
591
|
+
}
|
|
592
|
+
async getEgg(nestId, eggId, options) {
|
|
593
|
+
return this.http.get(`${BASE$3}/${nestId}/eggs/${eggId}`, options);
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/application/node-manager.ts
|
|
599
|
+
const BASE$2 = "/api/application/nodes";
|
|
600
|
+
var NodeManager = class {
|
|
601
|
+
constructor(http) {
|
|
602
|
+
this.http = http;
|
|
603
|
+
}
|
|
604
|
+
async list(options) {
|
|
605
|
+
return this.http.getList(BASE$2, options);
|
|
606
|
+
}
|
|
607
|
+
async get(nodeId, options) {
|
|
608
|
+
return this.http.get(`${BASE$2}/${nodeId}`, options);
|
|
609
|
+
}
|
|
610
|
+
async getDeployable(options) {
|
|
611
|
+
return this.http.getList(`${BASE$2}/deployable`, options);
|
|
612
|
+
}
|
|
613
|
+
async create(params) {
|
|
614
|
+
return this.http.post(BASE$2, params);
|
|
615
|
+
}
|
|
616
|
+
async update(nodeId, params) {
|
|
617
|
+
return this.http.patch(`${BASE$2}/${nodeId}`, params);
|
|
618
|
+
}
|
|
619
|
+
async delete(nodeId) {
|
|
620
|
+
await this.http.delete(`${BASE$2}/${nodeId}`);
|
|
621
|
+
}
|
|
622
|
+
async getConfig(nodeId) {
|
|
623
|
+
return (await this.http.raw("GET", `${BASE$2}/${nodeId}/configuration`)).json();
|
|
624
|
+
}
|
|
625
|
+
async listAllocations(nodeId, options) {
|
|
626
|
+
return this.http.getList(`${BASE$2}/${nodeId}/allocations`, options);
|
|
627
|
+
}
|
|
628
|
+
async createAllocations(nodeId, params) {
|
|
629
|
+
await this.http.post(`${BASE$2}/${nodeId}/allocations`, params);
|
|
630
|
+
}
|
|
631
|
+
async deleteAllocation(nodeId, allocationId) {
|
|
632
|
+
await this.http.delete(`${BASE$2}/${nodeId}/allocations/${allocationId}`);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/application/server-manager.ts
|
|
638
|
+
const BASE$1 = "/api/application/servers";
|
|
639
|
+
var ServerManager = class {
|
|
640
|
+
constructor(http) {
|
|
641
|
+
this.http = http;
|
|
642
|
+
}
|
|
643
|
+
async list(options) {
|
|
644
|
+
return this.http.getList(BASE$1, options);
|
|
645
|
+
}
|
|
646
|
+
async get(serverId, options) {
|
|
647
|
+
return this.http.get(`${BASE$1}/${serverId}`, options);
|
|
648
|
+
}
|
|
649
|
+
async getByExternalId(externalId, options) {
|
|
650
|
+
return this.http.get(`${BASE$1}/external/${externalId}`, options);
|
|
651
|
+
}
|
|
652
|
+
async create(params) {
|
|
653
|
+
return this.http.post(BASE$1, params);
|
|
654
|
+
}
|
|
655
|
+
async updateDetails(serverId, params) {
|
|
656
|
+
return this.http.patch(`${BASE$1}/${serverId}/details`, params);
|
|
657
|
+
}
|
|
658
|
+
async updateBuild(serverId, params) {
|
|
659
|
+
return this.http.patch(`${BASE$1}/${serverId}/build`, params);
|
|
660
|
+
}
|
|
661
|
+
async updateStartup(serverId, params) {
|
|
662
|
+
return this.http.patch(`${BASE$1}/${serverId}/startup`, params);
|
|
663
|
+
}
|
|
664
|
+
async suspend(serverId) {
|
|
665
|
+
await this.http.post(`${BASE$1}/${serverId}/suspend`);
|
|
666
|
+
}
|
|
667
|
+
async unsuspend(serverId) {
|
|
668
|
+
await this.http.post(`${BASE$1}/${serverId}/unsuspend`);
|
|
669
|
+
}
|
|
670
|
+
async reinstall(serverId) {
|
|
671
|
+
await this.http.post(`${BASE$1}/${serverId}/reinstall`);
|
|
672
|
+
}
|
|
673
|
+
async delete(serverId) {
|
|
674
|
+
await this.http.delete(`${BASE$1}/${serverId}`);
|
|
675
|
+
}
|
|
676
|
+
async forceDelete(serverId) {
|
|
677
|
+
await this.http.delete(`${BASE$1}/${serverId}/force`);
|
|
678
|
+
}
|
|
679
|
+
async listDatabases(serverId, options) {
|
|
680
|
+
return this.http.getList(`${BASE$1}/${serverId}/databases`, options);
|
|
681
|
+
}
|
|
682
|
+
async getDatabase(serverId, databaseId, options) {
|
|
683
|
+
return this.http.get(`${BASE$1}/${serverId}/databases/${databaseId}`, options);
|
|
684
|
+
}
|
|
685
|
+
async createDatabase(serverId, params) {
|
|
686
|
+
return this.http.post(`${BASE$1}/${serverId}/databases`, params);
|
|
687
|
+
}
|
|
688
|
+
async resetDatabasePassword(serverId, databaseId) {
|
|
689
|
+
await this.http.post(`${BASE$1}/${serverId}/databases/${databaseId}/reset-password`);
|
|
690
|
+
}
|
|
691
|
+
async deleteDatabase(serverId, databaseId) {
|
|
692
|
+
await this.http.delete(`${BASE$1}/${serverId}/databases/${databaseId}`);
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
//#endregion
|
|
697
|
+
//#region src/application/user-manager.ts
|
|
698
|
+
const BASE = "/api/application/users";
|
|
699
|
+
var UserManager = class {
|
|
700
|
+
constructor(http) {
|
|
701
|
+
this.http = http;
|
|
702
|
+
}
|
|
703
|
+
async list(options) {
|
|
704
|
+
return this.http.getList(BASE, options);
|
|
705
|
+
}
|
|
706
|
+
async get(userId, options) {
|
|
707
|
+
return this.http.get(`${BASE}/${userId}`, options);
|
|
708
|
+
}
|
|
709
|
+
async getByExternalId(externalId, options) {
|
|
710
|
+
return this.http.get(`${BASE}/external/${externalId}`, options);
|
|
711
|
+
}
|
|
712
|
+
async create(params) {
|
|
713
|
+
return this.http.post(BASE, params);
|
|
714
|
+
}
|
|
715
|
+
async update(userId, params) {
|
|
716
|
+
return this.http.patch(`${BASE}/${userId}`, params);
|
|
717
|
+
}
|
|
718
|
+
async delete(userId) {
|
|
719
|
+
await this.http.delete(`${BASE}/${userId}`);
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
//#endregion
|
|
724
|
+
//#region src/application/index.ts
|
|
725
|
+
var PteroApplication = class {
|
|
726
|
+
users;
|
|
727
|
+
servers;
|
|
728
|
+
nodes;
|
|
729
|
+
locations;
|
|
730
|
+
nests;
|
|
731
|
+
http;
|
|
732
|
+
constructor(options) {
|
|
733
|
+
this.http = new HttpClient(options);
|
|
734
|
+
this.users = new UserManager(this.http);
|
|
735
|
+
this.servers = new ServerManager(this.http);
|
|
736
|
+
this.nodes = new NodeManager(this.http);
|
|
737
|
+
this.locations = new LocationManager(this.http);
|
|
738
|
+
this.nests = new NestManager(this.http);
|
|
739
|
+
}
|
|
740
|
+
/** Current rate limit info from the last API response. */
|
|
741
|
+
get rateLimit() {
|
|
742
|
+
return this.http.rateLimit;
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
//#endregion
|
|
747
|
+
//#region src/websocket/websocket-manager.ts
|
|
748
|
+
var WebSocketManager = class {
|
|
749
|
+
ws = null;
|
|
750
|
+
listeners = /* @__PURE__ */ new Map();
|
|
751
|
+
reconnectAttempts = 0;
|
|
752
|
+
reconnectTimer = null;
|
|
753
|
+
intentionalClose = false;
|
|
754
|
+
origin;
|
|
755
|
+
serverUuid;
|
|
756
|
+
getToken;
|
|
757
|
+
maxReconnectDelay;
|
|
758
|
+
autoReconnect;
|
|
759
|
+
constructor(options) {
|
|
760
|
+
this.origin = options.origin.replace(/\/+$/, "");
|
|
761
|
+
this.serverUuid = options.serverUuid;
|
|
762
|
+
this.getToken = options.getToken;
|
|
763
|
+
this.maxReconnectDelay = options.maxReconnectDelay ?? 3e4;
|
|
764
|
+
this.autoReconnect = options.autoReconnect ?? true;
|
|
765
|
+
}
|
|
766
|
+
/** Connect to the WebSocket server. */
|
|
767
|
+
async connect() {
|
|
768
|
+
if (this.ws) return;
|
|
769
|
+
this.intentionalClose = false;
|
|
770
|
+
const token = await this.getToken();
|
|
771
|
+
const url = `${this.origin.startsWith("https") ? "wss" : "ws"}://${this.origin.replace(/^https?:\/\//, "")}/api/servers/${this.serverUuid}/ws`;
|
|
772
|
+
this.ws = new WebSocket(url);
|
|
773
|
+
this.ws.onopen = () => {
|
|
774
|
+
this.reconnectAttempts = 0;
|
|
775
|
+
this.sendAuth(token);
|
|
776
|
+
};
|
|
777
|
+
this.ws.onmessage = (event) => {
|
|
778
|
+
this.handleMessage(event.data);
|
|
779
|
+
};
|
|
780
|
+
this.ws.onclose = () => {
|
|
781
|
+
this.ws = null;
|
|
782
|
+
if (!this.intentionalClose && this.autoReconnect) this.scheduleReconnect();
|
|
783
|
+
};
|
|
784
|
+
this.ws.onerror = () => {};
|
|
785
|
+
}
|
|
786
|
+
/** Disconnect from the WebSocket server. */
|
|
787
|
+
disconnect() {
|
|
788
|
+
this.intentionalClose = true;
|
|
789
|
+
if (this.reconnectTimer) {
|
|
790
|
+
clearTimeout(this.reconnectTimer);
|
|
791
|
+
this.reconnectTimer = null;
|
|
792
|
+
}
|
|
793
|
+
if (this.ws) {
|
|
794
|
+
this.ws.close(1e3);
|
|
795
|
+
this.ws = null;
|
|
796
|
+
}
|
|
797
|
+
this.reconnectAttempts = 0;
|
|
798
|
+
}
|
|
799
|
+
/** Send a console command to the server. */
|
|
800
|
+
sendCommand(command) {
|
|
801
|
+
this.send("send command", [command]);
|
|
802
|
+
}
|
|
803
|
+
/** Send a power action to the server. */
|
|
804
|
+
sendPowerAction(action) {
|
|
805
|
+
this.send("set state", [action]);
|
|
806
|
+
}
|
|
807
|
+
/** Register an event handler. */
|
|
808
|
+
on(event, handler) {
|
|
809
|
+
let handlers = this.listeners.get(event);
|
|
810
|
+
if (!handlers) {
|
|
811
|
+
handlers = /* @__PURE__ */ new Set();
|
|
812
|
+
this.listeners.set(event, handlers);
|
|
813
|
+
}
|
|
814
|
+
handlers.add(handler);
|
|
815
|
+
return this;
|
|
816
|
+
}
|
|
817
|
+
/** Remove an event handler. */
|
|
818
|
+
off(event, handler) {
|
|
819
|
+
const handlers = this.listeners.get(event);
|
|
820
|
+
if (handlers) {
|
|
821
|
+
handlers.delete(handler);
|
|
822
|
+
if (handlers.size === 0) this.listeners.delete(event);
|
|
823
|
+
}
|
|
824
|
+
return this;
|
|
825
|
+
}
|
|
826
|
+
/** Whether the WebSocket is currently connected. */
|
|
827
|
+
get connected() {
|
|
828
|
+
return this.ws?.readyState === 1;
|
|
829
|
+
}
|
|
830
|
+
send(event, args) {
|
|
831
|
+
if (!this.ws || this.ws.readyState !== 1) return;
|
|
832
|
+
this.ws.send(JSON.stringify({
|
|
833
|
+
event,
|
|
834
|
+
args
|
|
835
|
+
}));
|
|
836
|
+
}
|
|
837
|
+
sendAuth(token) {
|
|
838
|
+
this.send("auth", [token]);
|
|
839
|
+
}
|
|
840
|
+
handleMessage(raw) {
|
|
841
|
+
let message;
|
|
842
|
+
try {
|
|
843
|
+
message = JSON.parse(raw);
|
|
844
|
+
} catch {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const { event, args } = message;
|
|
848
|
+
if (event === "token expiring") this.refreshToken();
|
|
849
|
+
this.emit(event, args);
|
|
850
|
+
}
|
|
851
|
+
emit(event, args) {
|
|
852
|
+
const handlers = this.listeners.get(event);
|
|
853
|
+
if (!handlers) return;
|
|
854
|
+
switch (event) {
|
|
855
|
+
case "auth success":
|
|
856
|
+
case "token expiring":
|
|
857
|
+
case "token expired":
|
|
858
|
+
case "install started":
|
|
859
|
+
case "install completed":
|
|
860
|
+
for (const handler of handlers) handler();
|
|
861
|
+
break;
|
|
862
|
+
case "stats": {
|
|
863
|
+
const statsJson = args?.[0];
|
|
864
|
+
if (statsJson) try {
|
|
865
|
+
const stats = JSON.parse(statsJson);
|
|
866
|
+
for (const handler of handlers) handler(stats);
|
|
867
|
+
} catch {}
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
case "status": {
|
|
871
|
+
const status = args?.[0];
|
|
872
|
+
if (status) for (const handler of handlers) handler(status);
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
default: {
|
|
876
|
+
const value = args?.[0];
|
|
877
|
+
if (value !== void 0) for (const handler of handlers) handler(value);
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
async refreshToken() {
|
|
883
|
+
try {
|
|
884
|
+
const token = await this.getToken();
|
|
885
|
+
this.sendAuth(token);
|
|
886
|
+
} catch {}
|
|
887
|
+
}
|
|
888
|
+
scheduleReconnect() {
|
|
889
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), this.maxReconnectDelay);
|
|
890
|
+
this.reconnectAttempts++;
|
|
891
|
+
this.reconnectTimer = setTimeout(() => {
|
|
892
|
+
this.reconnectTimer = null;
|
|
893
|
+
this.connect();
|
|
894
|
+
}, delay);
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
//#endregion
|
|
899
|
+
//#region src/types/websocket.ts
|
|
900
|
+
/** WebSocket close codes used by the Pterodactyl daemon. */
|
|
901
|
+
let WebSocketCloseCode = /* @__PURE__ */ function(WebSocketCloseCode$1) {
|
|
902
|
+
WebSocketCloseCode$1[WebSocketCloseCode$1["Normal"] = 1e3] = "Normal";
|
|
903
|
+
WebSocketCloseCode$1[WebSocketCloseCode$1["GoingAway"] = 1001] = "GoingAway";
|
|
904
|
+
WebSocketCloseCode$1[WebSocketCloseCode$1["AbnormalClosure"] = 1006] = "AbnormalClosure";
|
|
905
|
+
WebSocketCloseCode$1[WebSocketCloseCode$1["AuthenticationFailed"] = 4001] = "AuthenticationFailed";
|
|
906
|
+
WebSocketCloseCode$1[WebSocketCloseCode$1["TokenExpired"] = 4004] = "TokenExpired";
|
|
907
|
+
return WebSocketCloseCode$1;
|
|
908
|
+
}({});
|
|
909
|
+
|
|
910
|
+
//#endregion
|
|
911
|
+
export { AccountManager, BackupManager, DatabaseManager, FileManager, HttpClient, LocationManager, NestManager, NetworkManager, NodeManager, PteroApplication, PteroClient, PteroError, PteroRateLimitError, PteroValidationError, ScheduleManager, ServerContext, ServerManager, ServersManager, SubuserManager, UserManager, WebSocketCloseCode, WebSocketManager };
|