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.
- package/dist/wisp_api/index.d.ts +6 -0
- package/dist/wisp_api/index.js +8 -0
- package/dist/wisp_socket/filesystem.d.ts +60 -0
- package/dist/wisp_socket/filesystem.js +97 -0
- package/dist/wisp_socket/git.d.ts +57 -0
- package/dist/wisp_socket/git.js +76 -0
- package/dist/wisp_socket/index.d.ts +37 -18
- package/dist/wisp_socket/index.js +102 -157
- package/dist/wisp_socket/pool.d.ts +192 -48
- package/dist/wisp_socket/pool.js +132 -33
- package/dist/wisp_socket/ws_adapter.d.ts +72 -0
- package/dist/wisp_socket/ws_adapter.js +130 -0
- package/package.json +5 -4
- package/.github/workflows/release.yml +0 -77
- package/tsconfig.json +0 -19
- package/wisp.ts +0 -43
- package/wisp_api/apis/allocations.ts +0 -71
- package/wisp_api/apis/audit_log.ts +0 -81
- package/wisp_api/apis/backups.ts +0 -168
- package/wisp_api/apis/databases.ts +0 -80
- package/wisp_api/apis/fastdl.ts +0 -22
- package/wisp_api/apis/filesystem.ts +0 -291
- package/wisp_api/apis/index.ts +0 -135
- package/wisp_api/apis/mods.ts +0 -53
- package/wisp_api/apis/schedules.ts +0 -270
- package/wisp_api/apis/servers.ts +0 -155
- package/wisp_api/apis/startup.ts +0 -65
- package/wisp_api/apis/subusers.ts +0 -159
- package/wisp_api/index.ts +0 -57
- package/wisp_socket/index.ts +0 -495
- package/wisp_socket/pool.ts +0 -369
|
@@ -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
|
-
}
|
package/wisp_socket/index.ts
DELETED
|
@@ -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
|
-
}
|