wispjs 2.4.0 → 3.0.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.
@@ -1,159 +0,0 @@
1
- import { WispAPICore } from "./index";
2
- import type { PaginationData } from "./index";
3
-
4
- export type SupportPermissionType = "server:support.update";
5
- export type ControlPermissionType = "server:control.console" | "server:control.command" | "server:control.start" | "server:control.stop" | "server:control.restart";
6
- export type SubuserPermissionType = "server:subuser.read" | "server:subuser.update" | "server:subuser.create" | "server:subuser.delete";
7
- export type AllocationPermissionType = "server:allocation.read" | "server:allocation.update";
8
- export type StartupPermissionType = "server:startup.read" | "server:startup.update";
9
- export type DatabasePermissionType = "server:database.read" | "server:database.update" | "server:database.create" | "server:database.update";
10
- export type FilePermissionType = "server:file.sftp" | "server:file.list" | "server:file.read" | "server:file.write" | "server:file.delete" | "server:file.archive" | "server:file.git" | "server:file.steam_workshop";
11
- export type SchedulePermissionType = "server:schedule.read" | "server:schedule.update" | "server:schedule.create" | "server:schedule.delete";
12
- export type BackupPermissionType = "server:backup.read" | "server:backup.update" | "server:backup.create" | "server:backup.delete" | "server:backup.deploy" | "server:backup.download";
13
- export type DetailsPermissionType = "server:details.read" | "server:details.update";
14
- export type AuditPermissionType = "server:audit.read";
15
- export type FastDLPermissionType = "server:fastdl.read" | "server:fastdl.update";
16
- export type ModPermissionType = "server:mod.read" | "server:mod.update";
17
- export type MonitorPermissionType = "server:monitor.read" | "server:monitor.update";
18
- export type ReinstallPermissionType = "server:reinstall.update";
19
- export type Permission = SupportPermissionType | ControlPermissionType | SubuserPermissionType | AllocationPermissionType | StartupPermissionType | DatabasePermissionType | FilePermissionType | SchedulePermissionType | BackupPermissionType | DetailsPermissionType | AuditPermissionType | FastDLPermissionType | ModPermissionType | MonitorPermissionType | ReinstallPermissionType;
20
-
21
- export interface User {
22
- object: "user";
23
- attributes: {
24
- email: string;
25
- name_first: string;
26
- naem_last: string;
27
- has_2fa: boolean;
28
- }
29
- }
30
-
31
- export interface Subuser {
32
- object: "server_subuser";
33
- attributes: {
34
- id: number;
35
- permissions: Permission[];
36
- created_at: string;
37
- updated_at: string;
38
- relationships: {
39
- user: User;
40
- }
41
- }
42
- }
43
-
44
- export interface GetSubusersResponse {
45
- object: "list";
46
- data: Subuser[];
47
- meta: {
48
- pagination: PaginationData;
49
- }
50
- }
51
-
52
- export interface GetAllSubuserPermissionsResponse {
53
- permissions: Permission[];
54
- assignable: Permission[];
55
- }
56
-
57
- /**
58
- * Handles interfacing with the Subusers API
59
- *
60
- * @public
61
- */
62
- export class SubusersAPI {
63
- constructor(private core: WispAPICore) {}
64
-
65
-
66
- /**
67
- * Lists all Subusers for the Server
68
- *
69
- * @public
70
- */
71
- async List(): Promise<GetSubusersResponse> {
72
- const response = await this.core.makeRequest("GET", "subusers", { include: "user" });
73
- const data: GetSubusersResponse = await response.json();
74
-
75
- return data;
76
- }
77
-
78
-
79
- /**
80
- * Retrieves the details for the Subuser
81
- *
82
- * @param id The ID of the Subuser
83
- *
84
- * @public
85
- */
86
- async GetDetails(id: string): Promise<Subuser> {
87
- const response = await this.core.makeRequest("GET", `subusers/${id}`, { include: "user" });
88
- const data: Subuser = await response.json();
89
-
90
- return data;
91
- }
92
-
93
-
94
- /**
95
- * Get all permissions available to Subusers
96
- *
97
- * @public
98
- */
99
- async GetAllPermissions(): Promise<GetAllSubuserPermissionsResponse> {
100
- const response = await this.core.makeRequest("GET", "subusers/permissions");
101
- const data: GetAllSubuserPermissionsResponse = await response.json();
102
-
103
- return data;
104
- }
105
-
106
-
107
- /**
108
- * Creates a new Subuser
109
- *
110
- * @param email The email for the Subuser
111
- * @param permissions The Permissions to grant to the Subuser
112
- *
113
- * @public
114
- */
115
- async Create(email: string, permissions: Permission[]): Promise<Subuser> {
116
- const requestData = {
117
- email: email,
118
- permissions: permissions
119
- }
120
-
121
- const response = await this.core.makeRequest("POST", "subusers", requestData);
122
- const data: Subuser = await response.json();
123
-
124
- return data;
125
- }
126
-
127
-
128
- /**
129
- * Updates the Subuser
130
- *
131
- * @param id The ID of the Subuser
132
- * @param email The new email of the Subuser
133
- * @param permissions The new permissions for the Subuser
134
- *
135
- * @public
136
- */
137
- async Update(id: string, email: string, permissions: Permission[]): Promise<Subuser> {
138
- const data = {
139
- email: email,
140
- permissions: permissions
141
- }
142
-
143
- const response = await this.core.makeRequest("PATCH", `subusers/${id}`, data);
144
- const responseData: Subuser = await response.json();
145
-
146
- return responseData;
147
- }
148
-
149
- /**
150
- * Deletes the Subuser
151
- *
152
- * @param id The ID of the Subuser
153
- *
154
- * @public
155
- */
156
- async Delete(id: string): Promise<void> {
157
- await this.core.makeRequest("DELETE", `subusers/${id}`);
158
- }
159
- }
package/wisp_api/index.ts DELETED
@@ -1,57 +0,0 @@
1
- import { WispAPICore } from "./apis/index.js";
2
- import { AllocationsAPI } from "./apis/allocations.js";
3
- import { AuditLogsAPI } from "./apis/audit_log.js";
4
- import { BackupsAPI } from "./apis/backups.js";
5
- import { DatabasesAPI } from "./apis/databases.js";
6
- import { FastDLAPI } from "./apis/fastdl.js";
7
- import { FilesystemAPI } from "./apis/filesystem.js";
8
- import { ModsAPI } from "./apis/mods.js";
9
- import { SchedulesAPI } from "./apis/schedules.js";
10
- import { ServersAPI } from "./apis/servers.js";
11
- import { StartupAPI } from "./apis/startup.js";
12
- import { SubusersAPI } from "./apis/subusers.js";
13
-
14
- /**
15
- * An Interface for the Wisp HTTP API
16
- *
17
- * @public
18
- */
19
- export class WispAPI {
20
- private core: WispAPICore;
21
-
22
- public Allocations: AllocationsAPI;
23
- public AuditLogs: AuditLogsAPI;
24
- public Backups: BackupsAPI;
25
- public Databases: DatabasesAPI;
26
- public FastDL: FastDLAPI;
27
- public Filesystem: FilesystemAPI;
28
- public Mods: ModsAPI;
29
- public Schedules: SchedulesAPI;
30
- public Servers: ServersAPI;
31
- public Startup: StartupAPI;
32
- public Subusers: SubusersAPI;
33
-
34
- /**
35
- * @param domain The domain name for your panel
36
- * @param uuid The UUID of the Server that all future API calls will reference
37
- * @param token The panel API token to use for authorization
38
- * @param logger The logger to use for all API logging
39
- *
40
- * @internal
41
- */
42
- constructor(domain: string, uuid: string, token: string, logger: any) {
43
- this.core = new WispAPICore(domain, uuid, token, logger);
44
-
45
- this.Allocations = new AllocationsAPI(this.core);
46
- this.AuditLogs = new AuditLogsAPI(this.core);
47
- this.Backups = new BackupsAPI(this.core);
48
- this.Databases = new DatabasesAPI(this.core);
49
- this.FastDL = new FastDLAPI(this.core);
50
- this.Filesystem = new FilesystemAPI(this.core);
51
- this.Mods = new ModsAPI(this.core);
52
- this.Schedules = new SchedulesAPI(this.core);
53
- this.Servers = new ServersAPI(this.core);
54
- this.Startup = new StartupAPI(this.core);
55
- this.Subusers = new SubusersAPI(this.core);
56
- }
57
- }
@@ -1,495 +0,0 @@
1
- import stripAnsi from 'strip-ansi';
2
- import { WebsocketPool } from "./pool.js"
3
- import { ConsoleMessage, FilesearchResults } from "./pool"
4
- import { GitPullData, GitPullResult } from "./pool.js"
5
- import { GitCloneData, GitCloneResult } from "./pool.js"
6
-
7
- import type { WispAPI } from "../wisp_api/index.js"
8
-
9
-
10
- /**
11
- * The Websocket information returned from the API
12
- *
13
- * @param token The token to use when authenticating with the `auth` command in the Websocket
14
- * @param url The actual URL of the Websocket
15
- *
16
- * @internal
17
- */
18
- export interface WebsocketInfo {
19
- token: string;
20
- url: string;
21
- }
22
-
23
-
24
- export type WebsocketDetailsPreprocessor = (info: WebsocketInfo) => void;
25
-
26
-
27
- export interface WispSocket {
28
- pool: WebsocketPool;
29
- logger: any;
30
- api: WispAPI;
31
- url: string | undefined;
32
- token: string | undefined;
33
- ghToken: string | undefined;
34
- consoleCallbacks: ((message: string) => void)[];
35
- detailsPreprocessor: WebsocketDetailsPreprocessor | undefined;
36
- }
37
-
38
-
39
- /**
40
- * The primary interface to the Websocket API
41
- *
42
- * @internal
43
- */
44
- export class WispSocket {
45
- constructor(logger: any, api: any, ghToken: string | undefined) {
46
- this.logger = logger
47
- this.api = api
48
- this.ghToken = ghToken
49
- this.consoleCallbacks = []
50
- }
51
-
52
-
53
- /**
54
- * Sets a callback to run on the Websocket Info before saving the details.
55
- *
56
- * @example
57
- * ```js
58
- * // Change the URL of the Websocket
59
- * wisp.socket.setWebsocketDetailsPreprocessor((info) => {
60
- * info.url = "wss://newurl.com"
61
- * })
62
- * ```
63
- *
64
- * @remarks
65
- * ℹ️ This can be used to modify the URL or token after its retrieved from the API
66
- *
67
- * @param preprocessor The callback to run when the data is received from the API
68
- *
69
- * @public
70
- */
71
- setWebsocketDetailsPreprocessor(preprocessor: WebsocketDetailsPreprocessor) {
72
- this.detailsPreprocessor = preprocessor;
73
- }
74
-
75
-
76
- /**
77
- * Creates a new Websocket Pool
78
- *
79
- * @throws Throws an error if the URL or token are not set yet
80
- * @internal
81
- */
82
- createPool() {
83
- if (!this.url || !this.token) {
84
- throw new Error("Attempted to create a pool without a URL or token")
85
- }
86
-
87
- this.pool = new WebsocketPool(this.url, this.token)
88
- }
89
-
90
-
91
- /**
92
- * Requests and saves the Websocket details from the API
93
- *
94
- * @internal
95
- */
96
- async setDetails() {
97
- try {
98
- const websocketInfo: WebsocketInfo = await this.api.Servers.GetWebsocketDetails()
99
- if (this.detailsPreprocessor) {
100
- this.detailsPreprocessor(websocketInfo);
101
- }
102
-
103
- this.url = websocketInfo.url
104
- this.token = websocketInfo.token
105
-
106
- this.logger.info("Got Websocket Details.", this.url, this.token)
107
- } catch(e) {
108
- this.logger.error(`Failed to get websocket details: ${e}`)
109
- throw(e)
110
- }
111
- }
112
-
113
-
114
- /**
115
- * Disconnects from the websocket
116
- *
117
- * @internal
118
- */
119
- async disconnect() {
120
- if (this.pool) {
121
- await this.pool.disconnect()
122
- }
123
- }
124
-
125
-
126
- /**
127
- * Verifies that the pool is created and ready to use
128
- *
129
- * @internal
130
- */
131
- async verifyPool() {
132
- if (!this.pool) {
133
- await this.setDetails()
134
- this.createPool()
135
- }
136
- }
137
-
138
-
139
- /**
140
- * Searches all file contents for the given query
141
- *
142
- * @param query The query string to search for
143
- * @param timeout How long to wait (in ms) for results before timing out
144
- *
145
- * @public
146
- */
147
- async filesearch(query: string, timeout: number = 10000): Promise<FilesearchResults> {
148
- this.logger.info("Running filesearch with: ", query)
149
- await this.verifyPool()
150
-
151
- return await this.pool.run((worker) => {
152
- const socket = worker.socket
153
- const logger = worker.logger
154
- logger.log("Running filesearch:", query)
155
-
156
- return new Promise<FilesearchResults>((resolve, reject) => {
157
- const timeoutObj = setTimeout(() => {
158
- socket.off("filesearch-results")
159
- logger.error("Rejected filesearch: 'Timeout'")
160
- reject()
161
- }, timeout)
162
-
163
- socket.once("filesearch-results", (data) => {
164
- clearTimeout(timeoutObj)
165
- resolve(data)
166
- })
167
-
168
- socket.emit("filesearch-start", query)
169
- })
170
- })
171
- }
172
-
173
-
174
- /**
175
- * Performs a git pull operation on the given directory
176
- *
177
- * @param dir The full directory path to perform a pull on
178
- * @param timeout In milliseconds, how long to wait before timing out
179
- *
180
- * @public
181
- */
182
- async gitPull(dir: string, useAuth: boolean = false, timeout: number = 10000) {
183
- await this.verifyPool()
184
-
185
- const pullResult = await this.pool.run((worker) => {
186
- const socket = worker.socket
187
- const logger = worker.logger
188
- logger.log("Running gitPull:", dir)
189
-
190
- return new Promise<GitPullResult>((resolve, reject) => {
191
- let isPrivate = false
192
- let finished: (success: boolean, output: string) => void
193
-
194
- const timeoutObj = setTimeout(() => {
195
- logger.error("Rejected gitPull: 'Timeout'")
196
- finished(false, "Timeout")
197
- }, timeout)
198
-
199
- finished = (success: boolean, output: string) => {
200
- socket.removeAllListeners("git-pull")
201
- socket.removeAllListeners("git-error")
202
- socket.removeAllListeners("git-success")
203
-
204
- const result: GitPullResult = {
205
- output: output,
206
- isPrivate: isPrivate
207
- }
208
-
209
- if (success) {
210
- resolve(result)
211
- } else {
212
- logger.error("Rejected gitPull:", dir, output)
213
- reject(output)
214
- }
215
-
216
- clearTimeout(timeoutObj)
217
- }
218
-
219
- const sendRequest = (includeAuth: boolean = false) => {
220
- const data: GitPullData = { dir: dir }
221
-
222
- if (includeAuth) {
223
- if (!this.ghToken) {
224
- logger.error("No GitHub token set, can't authenticate")
225
- return finished(false, "Authentication is required, but no GitHub token was set. Can't pull!")
226
- }
227
-
228
- isPrivate = true
229
- data.authkey = this.ghToken
230
- }
231
-
232
- socket.emit("git-pull", data)
233
- }
234
-
235
- socket.once("git-pull", (data) => {
236
- logger.log(`Updating ${data}`)
237
- })
238
-
239
- socket.once("git-success", (commit) => {
240
- logger.log(`Addon updated to ${commit}`)
241
-
242
- if (!commit) {
243
- logger.log("No commit given!")
244
- }
245
-
246
- finished(true, commit || "")
247
- })
248
-
249
- socket.on("git-error", (message) => {
250
- if (message === "Remote authentication required but no callback set") {
251
- logger.log(`Remote authentication required, trying again with authkey: ${dir}`)
252
- sendRequest(true)
253
- } else {
254
- logger.log(`Error updating addon: ${message}`)
255
- finished(false, message)
256
- }
257
- })
258
-
259
- sendRequest(useAuth)
260
- })
261
- })
262
-
263
- return pullResult
264
- }
265
-
266
-
267
- /**
268
- * Clones a new Repo to the given directory
269
- *
270
- * @param url The HTTPS URL of the repository
271
- * @param dir The full path of the directory to clone the repository to
272
- * @param branch The branch of the repository to clone
273
- * @param timeout In milliseconds, how long to wait before timing out
274
- *
275
- * @public
276
- */
277
- async gitClone(url: string, dir: string, branch: string, timeout: number = 20000) {
278
- await this.verifyPool()
279
-
280
- return await this.pool.run((worker) => {
281
- const socket = worker.socket
282
- const logger = worker.logger
283
- logger.log("Running gitClone:", url, dir, branch)
284
-
285
- return new Promise<GitCloneResult>((resolve, reject) => {
286
- let isPrivate = false
287
- let finished: (success: boolean, message?: string) => void
288
-
289
- const timeoutObj = setTimeout(() => {
290
- logger.error("Rejected gitClone: 'Timeout'")
291
- finished(false, "Timeout")
292
- }, timeout)
293
-
294
- finished = (success: boolean, message?: string) => {
295
- socket.removeAllListeners("git-clone")
296
- socket.removeAllListeners("git-error")
297
- socket.removeAllListeners("git-success")
298
-
299
- if (success) {
300
- const result: GitCloneResult = {
301
- isPrivate: isPrivate
302
- }
303
-
304
- resolve(result)
305
- } else {
306
- logger.error("Rejected gitClone:", url, dir, branch, message)
307
- reject(message)
308
- }
309
-
310
- clearTimeout(timeoutObj)
311
- }
312
-
313
- const sendRequest = (includeAuth: boolean = false) => {
314
- const data: GitCloneData = { dir: dir, url: url, branch: branch }
315
-
316
- if (includeAuth) {
317
- if (!this.ghToken) {
318
- logger.error("No GitHub token set, can't authenticate")
319
- return finished(false, "Authentication is required, but no GitHub token was set. Can't clone!")
320
- }
321
-
322
- isPrivate = true
323
- data.authkey = this.ghToken
324
- }
325
-
326
- socket.emit("git-clone", data)
327
- }
328
-
329
- socket.once("git-clone", (data) => {
330
- logger.log(`Cloning ${data}`)
331
- })
332
-
333
- socket.once("git-success", () => {
334
- logger.log("Project successfully cloned")
335
- finished(true)
336
- })
337
-
338
- socket.on("git-error", (message) => {
339
- if (message === "Remote authentication required but no callback set") {
340
- logger.log(`Remote authentication required, trying again with authkey: ${dir}`)
341
- sendRequest(true)
342
- } else {
343
- logger.log("Error cloning repo:", url, dir, branch, message)
344
- finished(false, message)
345
- }
346
- })
347
-
348
- sendRequest()
349
- })
350
- })
351
- }
352
-
353
-
354
- /**
355
- * Sets up the console listener worker
356
- *
357
- * @internal
358
- */
359
- setupConsoleListener() {
360
- this.verifyPool().then(() => {
361
- this.pool.run((worker) => {
362
- const logger = worker.logger
363
- logger.log("Running setupConsoleListener")
364
-
365
- return new Promise<void>((resolve) => {
366
- worker.socket.on("console", (data: ConsoleMessage) => {
367
- const line = data.line
368
-
369
- if (this.consoleCallbacks.length == 0) {
370
- return resolve()
371
- }
372
-
373
- this.consoleCallbacks.forEach((callback) => {
374
- try {
375
- callback(line)
376
- } catch(e) {
377
- logger.error("Failed to run console callback", e)
378
- }
379
- })
380
- })
381
- })
382
- })
383
- })
384
- }
385
-
386
-
387
- /**
388
- * Adds a new callback that will run any time a console message is rececived
389
- *
390
- * @param callback The callback to run, takes a single param, `message`, a string
391
- *
392
- * @public
393
- */
394
- addConsoleListener(callback: (message: string) => void) {
395
- if (this.consoleCallbacks.length == 0) {
396
- this.setupConsoleListener()
397
- }
398
-
399
- this.consoleCallbacks.push(callback)
400
- }
401
-
402
-
403
- /**
404
- * Removes a previously added console message callback
405
- *
406
- * @param callback The callback function that was previously added
407
- *
408
- * @public
409
- */
410
- removeConsoleListener(callback: (message: string) => void) {
411
- const index = this.consoleCallbacks.indexOf(callback)
412
- if (index == -1) { return }
413
-
414
- this.consoleCallbacks.splice(index, 1)
415
- }
416
-
417
-
418
- /**
419
- * Sends a command to the server and then waits until output with the given prefix is seen in a console message
420
- *
421
- * @example
422
- * Runs a custom lua command that will prefix its output with our nonce, then prints the output from that command
423
- * ```lua
424
- * -- lua/autorun/server/nonce_example.lua
425
- * concommand.Add( "myCommand", function( ply, _, args )
426
- * if IsValid( ply ) then return end
427
- *
428
- * local nonce = args[1]
429
- * print( nonce .. "Command output" )
430
- * end )
431
- * ```
432
- * ```js
433
- * const nonce = "abc123";
434
- * const command = `myCommand "${nonce}"`;
435
- * try {
436
- * const output = await wisp.socket.sendCommandNonce(nonce, command);
437
- * console.log("Output from command:", output);
438
- * catch (error) {
439
- * console.error(error);
440
- * }
441
- * ```
442
- *
443
- * @remarks
444
- * ℹ️ This is useful if you run code on your Server that will print output with the same prefix, letting you run commands and also receive output for it
445
- *
446
- * @param nonce The short, unique string that your output will be prefixed with
447
- * @param command The full command string to send
448
- * @param timeout In milliseconds, how long to wait for output before timing out
449
- *
450
- * @public
451
- */
452
- async sendCommandNonce(nonce: string, command: string, timeout: number = 1000) {
453
- await this.verifyPool()
454
-
455
- return await this.pool.run((worker) => {
456
- const socket = worker.socket
457
- const logger = worker.logger
458
- logger.log("Running sendCommandNonce: ", nonce, command)
459
-
460
- return new Promise<string>((resolve: Function, reject: Function) => {
461
- let output = ""
462
- let callback: (data: ConsoleMessage) => void
463
-
464
- const timeoutObj = setTimeout(() => {
465
- logger.error(`Command timed out current output: '${output}'`)
466
- socket.off("console", callback)
467
- logger.log("Rejected sendCommandNonce 'Timeout'", nonce, command)
468
- reject("Timeout")
469
- }, timeout)
470
-
471
- callback = (data: ConsoleMessage) => {
472
- const line = data.line
473
- const clean = stripAnsi(line)
474
-
475
- if (clean.startsWith(nonce)) {
476
- const message = clean.slice(nonce.length)
477
-
478
- if (message === "Done.") {
479
- socket.off("console", callback)
480
- clearTimeout(timeoutObj)
481
-
482
- resolve(output)
483
- } else {
484
- output += message
485
- timeoutObj.refresh()
486
- }
487
- }
488
- }
489
-
490
- socket.on("console", callback)
491
- socket.emit("send command", command)
492
- })
493
- })
494
- }
495
- }