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,5 +1,7 @@
|
|
|
1
1
|
import stripAnsi from 'strip-ansi';
|
|
2
2
|
import { WebsocketPool } from "./pool.js";
|
|
3
|
+
import { GitSocket } from "./git.js";
|
|
4
|
+
import { FilesystemSocket } from "./filesystem.js";
|
|
3
5
|
/**
|
|
4
6
|
* The primary interface to the Websocket API
|
|
5
7
|
*
|
|
@@ -11,6 +13,8 @@ export class WispSocket {
|
|
|
11
13
|
this.api = api;
|
|
12
14
|
this.ghToken = ghToken;
|
|
13
15
|
this.consoleCallbacks = [];
|
|
16
|
+
this.Git = new GitSocket(this);
|
|
17
|
+
this.Filesystem = new FilesystemSocket(this);
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
20
|
* Sets a callback to run on the Websocket Info before saving the details.
|
|
@@ -43,7 +47,16 @@ export class WispSocket {
|
|
|
43
47
|
if (!this.url || !this.token) {
|
|
44
48
|
throw new Error("Attempted to create a pool without a URL or token");
|
|
45
49
|
}
|
|
46
|
-
|
|
50
|
+
// Provider used by the pool to refresh the (short-lived) token when a
|
|
51
|
+
// worker needs to reconnect.
|
|
52
|
+
const refreshDetails = async () => {
|
|
53
|
+
await this.setDetails();
|
|
54
|
+
return { url: this.url, token: this.token };
|
|
55
|
+
};
|
|
56
|
+
// The Origin header is the panel the connection originates from, which
|
|
57
|
+
// is always the API domain.
|
|
58
|
+
const origin = `https://${this.api.domain}`;
|
|
59
|
+
this.pool = new WebsocketPool(this.url, this.token, origin, refreshDetails);
|
|
47
60
|
}
|
|
48
61
|
/**
|
|
49
62
|
* Requests and saves the Websocket details from the API
|
|
@@ -58,7 +71,7 @@ export class WispSocket {
|
|
|
58
71
|
}
|
|
59
72
|
this.url = websocketInfo.url;
|
|
60
73
|
this.token = websocketInfo.token;
|
|
61
|
-
this.logger.info(
|
|
74
|
+
this.logger.info(`Got Websocket Details. ${this.url} - ${this.token}`);
|
|
62
75
|
}
|
|
63
76
|
catch (e) {
|
|
64
77
|
this.logger.error(`Failed to get websocket details: ${e}`);
|
|
@@ -87,178 +100,112 @@ export class WispSocket {
|
|
|
87
100
|
}
|
|
88
101
|
}
|
|
89
102
|
/**
|
|
90
|
-
*
|
|
103
|
+
* Runs a job on an available pool worker, handing it the worker's socket
|
|
104
|
+
* and logger. Used for event-based flows (e.g. file search) that don't fit
|
|
105
|
+
* the {@link request} request/response protocol.
|
|
91
106
|
*
|
|
92
|
-
* @param
|
|
93
|
-
* @param timeout How long to wait (in ms) for results before timing out
|
|
107
|
+
* @param work The job to run; receives the worker and returns a Promise
|
|
94
108
|
*
|
|
95
|
-
* @
|
|
109
|
+
* @internal
|
|
96
110
|
*/
|
|
97
|
-
async
|
|
98
|
-
this.logger.info("Running filesearch with: ", query);
|
|
111
|
+
async runWorker(work) {
|
|
99
112
|
await this.verifyPool();
|
|
100
|
-
return await this.pool.run(
|
|
101
|
-
const socket = worker.socket;
|
|
102
|
-
const logger = worker.logger;
|
|
103
|
-
logger.log("Running filesearch:", query);
|
|
104
|
-
return new Promise((resolve, reject) => {
|
|
105
|
-
const timeoutObj = setTimeout(() => {
|
|
106
|
-
socket.off("filesearch-results");
|
|
107
|
-
logger.error("Rejected filesearch: 'Timeout'");
|
|
108
|
-
reject();
|
|
109
|
-
}, timeout);
|
|
110
|
-
socket.once("filesearch-results", (data) => {
|
|
111
|
-
clearTimeout(timeoutObj);
|
|
112
|
-
resolve(data);
|
|
113
|
-
});
|
|
114
|
-
socket.emit("filesearch-start", query);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
113
|
+
return await this.pool.run(work);
|
|
117
114
|
}
|
|
118
115
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @param dir The full directory path to perform a pull on
|
|
122
|
-
* @param timeout In milliseconds, how long to wait before timing out
|
|
116
|
+
* Generates a short, unique request id for {@link request} correlation.
|
|
123
117
|
*
|
|
124
|
-
* @
|
|
118
|
+
* @internal
|
|
125
119
|
*/
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const pullResult = await this.pool.run((worker) => {
|
|
129
|
-
const socket = worker.socket;
|
|
130
|
-
const logger = worker.logger;
|
|
131
|
-
logger.log("Running gitPull:", dir);
|
|
132
|
-
return new Promise((resolve, reject) => {
|
|
133
|
-
let isPrivate = false;
|
|
134
|
-
let finished;
|
|
135
|
-
const timeoutObj = setTimeout(() => {
|
|
136
|
-
logger.error("Rejected gitPull: 'Timeout'");
|
|
137
|
-
finished(false, "Timeout");
|
|
138
|
-
}, timeout);
|
|
139
|
-
finished = (success, output) => {
|
|
140
|
-
socket.removeAllListeners("git-pull");
|
|
141
|
-
socket.removeAllListeners("git-error");
|
|
142
|
-
socket.removeAllListeners("git-success");
|
|
143
|
-
const result = {
|
|
144
|
-
output: output,
|
|
145
|
-
isPrivate: isPrivate
|
|
146
|
-
};
|
|
147
|
-
if (success) {
|
|
148
|
-
resolve(result);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
logger.error("Rejected gitPull:", dir, output);
|
|
152
|
-
reject(output);
|
|
153
|
-
}
|
|
154
|
-
clearTimeout(timeoutObj);
|
|
155
|
-
};
|
|
156
|
-
const sendRequest = (includeAuth = false) => {
|
|
157
|
-
const data = { dir: dir };
|
|
158
|
-
if (includeAuth) {
|
|
159
|
-
if (!this.ghToken) {
|
|
160
|
-
logger.error("No GitHub token set, can't authenticate");
|
|
161
|
-
return finished(false, "Authentication is required, but no GitHub token was set. Can't pull!");
|
|
162
|
-
}
|
|
163
|
-
isPrivate = true;
|
|
164
|
-
data.authkey = this.ghToken;
|
|
165
|
-
}
|
|
166
|
-
socket.emit("git-pull", data);
|
|
167
|
-
};
|
|
168
|
-
socket.once("git-pull", (data) => {
|
|
169
|
-
logger.log(`Updating ${data}`);
|
|
170
|
-
});
|
|
171
|
-
socket.once("git-success", (commit) => {
|
|
172
|
-
logger.log(`Addon updated to ${commit}`);
|
|
173
|
-
if (!commit) {
|
|
174
|
-
logger.log("No commit given!");
|
|
175
|
-
}
|
|
176
|
-
finished(true, commit || "");
|
|
177
|
-
});
|
|
178
|
-
socket.on("git-error", (message) => {
|
|
179
|
-
if (message === "Remote authentication required but no callback set") {
|
|
180
|
-
logger.log(`Remote authentication required, trying again with authkey: ${dir}`);
|
|
181
|
-
sendRequest(true);
|
|
182
|
-
}
|
|
183
|
-
else {
|
|
184
|
-
logger.log(`Error updating addon: ${message}`);
|
|
185
|
-
finished(false, message);
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
sendRequest(useAuth);
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
return pullResult;
|
|
120
|
+
generateReqId() {
|
|
121
|
+
return Math.random().toString(36).slice(2, 14);
|
|
192
122
|
}
|
|
193
123
|
/**
|
|
194
|
-
*
|
|
124
|
+
* Issues a correlated `fs:request` to the backend and awaits its outcome.
|
|
125
|
+
*
|
|
126
|
+
* This is the low-level entry point for the git/filesystem protocol. The
|
|
127
|
+
* client emits `fs:request` with a JSON-string payload (`{ req, op, ...params }`),
|
|
128
|
+
* and the backend replies with one of three events, all correlated by `req`
|
|
129
|
+
* and all carrying a JSON-string `args[0]`:
|
|
130
|
+
*
|
|
131
|
+
* - `fs:result` — success; resolves with the parsed `data`
|
|
132
|
+
* - `fs:error` — failure; rejects with an {@link FsError} (plus collected `output`)
|
|
133
|
+
* - `fs:progress` — streaming stdout/stderr/progress lines (collected for error context)
|
|
134
|
+
*
|
|
135
|
+
* Typed convenience wrappers live on {@link GitSocket} ({@link WispSocket.Git})
|
|
136
|
+
* and {@link FilesystemSocket} ({@link WispSocket.Filesystem}); call this
|
|
137
|
+
* directly for ops that don't have a typed wrapper yet.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```js
|
|
141
|
+
* const status = await wisp.socket.request("git-status", { directory: "/garrysmod/addons/acf-3" })
|
|
142
|
+
* ```
|
|
195
143
|
*
|
|
196
|
-
* @param
|
|
197
|
-
* @param
|
|
198
|
-
* @param
|
|
199
|
-
* @param timeout In milliseconds, how long to wait before timing out
|
|
144
|
+
* @param op The operation name (e.g. `git-pull`, `list`)
|
|
145
|
+
* @param params Additional payload fields merged into the request (e.g. `{ directory }`)
|
|
146
|
+
* @param timeout In milliseconds, how long to wait for the result
|
|
200
147
|
*
|
|
201
148
|
* @public
|
|
202
149
|
*/
|
|
203
|
-
async
|
|
150
|
+
async request(op, params = {}, timeout = 10000) {
|
|
204
151
|
await this.verifyPool();
|
|
205
152
|
return await this.pool.run((worker) => {
|
|
206
153
|
const socket = worker.socket;
|
|
207
154
|
const logger = worker.logger;
|
|
208
|
-
|
|
155
|
+
const req = this.generateReqId();
|
|
156
|
+
logger.log(`Running fsRequest: ${op}`, params);
|
|
209
157
|
return new Promise((resolve, reject) => {
|
|
210
|
-
|
|
211
|
-
let
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
socket.removeAllListeners("git-clone");
|
|
218
|
-
socket.removeAllListeners("git-error");
|
|
219
|
-
socket.removeAllListeners("git-success");
|
|
220
|
-
if (success) {
|
|
221
|
-
const result = {
|
|
222
|
-
isPrivate: isPrivate
|
|
223
|
-
};
|
|
224
|
-
resolve(result);
|
|
158
|
+
const progress = [];
|
|
159
|
+
let resultHandler;
|
|
160
|
+
let errorHandler;
|
|
161
|
+
let progressHandler;
|
|
162
|
+
const parse = (raw) => {
|
|
163
|
+
try {
|
|
164
|
+
return JSON.parse(raw);
|
|
225
165
|
}
|
|
226
|
-
|
|
227
|
-
logger.error(
|
|
228
|
-
|
|
166
|
+
catch {
|
|
167
|
+
logger.error(`Failed to parse fs event for ${op}`, raw);
|
|
168
|
+
return undefined;
|
|
229
169
|
}
|
|
170
|
+
};
|
|
171
|
+
const cleanup = () => {
|
|
172
|
+
socket.off("fs:result", resultHandler);
|
|
173
|
+
socket.off("fs:error", errorHandler);
|
|
174
|
+
socket.off("fs:progress", progressHandler);
|
|
230
175
|
clearTimeout(timeoutObj);
|
|
231
176
|
};
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
177
|
+
const timeoutObj = setTimeout(() => {
|
|
178
|
+
cleanup();
|
|
179
|
+
logger.error(`fsRequest timed out: ${op} (${req})`);
|
|
180
|
+
reject(new Error(`fsRequest timed out: ${op}`));
|
|
181
|
+
}, timeout);
|
|
182
|
+
progressHandler = (raw) => {
|
|
183
|
+
const p = parse(raw);
|
|
184
|
+
if (!p || p.req !== req)
|
|
185
|
+
return;
|
|
186
|
+
const line = p.line ?? "";
|
|
187
|
+
progress.push(line);
|
|
188
|
+
logger.debug(`[${op}] ${p.kind}: ${line}`);
|
|
243
189
|
};
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
190
|
+
resultHandler = (raw) => {
|
|
191
|
+
const p = parse(raw);
|
|
192
|
+
if (!p || p.req !== req)
|
|
193
|
+
return;
|
|
194
|
+
cleanup();
|
|
195
|
+
resolve(p.data);
|
|
196
|
+
};
|
|
197
|
+
errorHandler = (raw) => {
|
|
198
|
+
const p = parse(raw);
|
|
199
|
+
if (!p || p.req !== req)
|
|
200
|
+
return;
|
|
201
|
+
cleanup();
|
|
202
|
+
logger.error(`fsRequest error: ${op} - ${p.code}: ${p.message}`);
|
|
203
|
+
reject({ ...p, output: progress.join("\n") });
|
|
204
|
+
};
|
|
205
|
+
socket.on("fs:result", resultHandler);
|
|
206
|
+
socket.on("fs:error", errorHandler);
|
|
207
|
+
socket.on("fs:progress", progressHandler);
|
|
208
|
+
socket.emit("fs:request", JSON.stringify({ req, op, ...params }));
|
|
262
209
|
});
|
|
263
210
|
});
|
|
264
211
|
}
|
|
@@ -273,8 +220,7 @@ export class WispSocket {
|
|
|
273
220
|
const logger = worker.logger;
|
|
274
221
|
logger.log("Running setupConsoleListener");
|
|
275
222
|
return new Promise((resolve) => {
|
|
276
|
-
worker.socket.on("console", (
|
|
277
|
-
const line = data.line;
|
|
223
|
+
worker.socket.on("console output", (line) => {
|
|
278
224
|
if (this.consoleCallbacks.length == 0) {
|
|
279
225
|
return resolve();
|
|
280
226
|
}
|
|
@@ -363,17 +309,16 @@ export class WispSocket {
|
|
|
363
309
|
let callback;
|
|
364
310
|
const timeoutObj = setTimeout(() => {
|
|
365
311
|
logger.error(`Command timed out current output: '${output}'`);
|
|
366
|
-
socket.off("console", callback);
|
|
312
|
+
socket.off("console output", callback);
|
|
367
313
|
logger.log("Rejected sendCommandNonce 'Timeout'", nonce, command);
|
|
368
314
|
reject("Timeout");
|
|
369
315
|
}, timeout);
|
|
370
|
-
callback = (
|
|
371
|
-
const line = data.line;
|
|
316
|
+
callback = (line) => {
|
|
372
317
|
const clean = stripAnsi(line);
|
|
373
318
|
if (clean.startsWith(nonce)) {
|
|
374
319
|
const message = clean.slice(nonce.length);
|
|
375
320
|
if (message === "Done.") {
|
|
376
|
-
socket.off("console", callback);
|
|
321
|
+
socket.off("console output", callback);
|
|
377
322
|
clearTimeout(timeoutObj);
|
|
378
323
|
resolve(output);
|
|
379
324
|
}
|
|
@@ -383,7 +328,7 @@ export class WispSocket {
|
|
|
383
328
|
}
|
|
384
329
|
}
|
|
385
330
|
};
|
|
386
|
-
socket.on("console", callback);
|
|
331
|
+
socket.on("console output", callback);
|
|
387
332
|
socket.emit("send command", command);
|
|
388
333
|
});
|
|
389
334
|
});
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type Logger = {
|
|
1
|
+
import { WispWebSocket } from "./ws_adapter.js";
|
|
2
|
+
export type Logger = {
|
|
3
3
|
log(...args: any[]): void;
|
|
4
4
|
error(...args: any[]): void;
|
|
5
5
|
debug(...args: any[]): void;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* The minimal worker surface handed to a job run via {@link WispSocket.runWorker}:
|
|
9
|
+
* the connected socket and a prefixed logger.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export interface SocketWorker {
|
|
14
|
+
socket: WispWebSocket;
|
|
15
|
+
logger: Logger;
|
|
16
|
+
}
|
|
7
17
|
/**
|
|
8
18
|
* The struct used to define the events that can be sent from the server to the client
|
|
9
19
|
*
|
|
@@ -11,13 +21,14 @@ type Logger = {
|
|
|
11
21
|
*/
|
|
12
22
|
export interface ServerToClientEvents {
|
|
13
23
|
"error": (message: string) => void;
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
24
|
+
"auth success": () => void;
|
|
25
|
+
"console output": (line: string) => void;
|
|
26
|
+
"status": (state: string) => void;
|
|
27
|
+
"stats": (statsJson: string) => void;
|
|
28
|
+
"filesearch results": (json: string) => void;
|
|
29
|
+
"fs:result": (json: string) => void;
|
|
30
|
+
"fs:error": (json: string) => void;
|
|
31
|
+
"fs:progress": (json: string) => void;
|
|
21
32
|
"initial status": (message: any) => void;
|
|
22
33
|
}
|
|
23
34
|
/**
|
|
@@ -27,72 +38,150 @@ export interface ServerToClientEvents {
|
|
|
27
38
|
*/
|
|
28
39
|
export interface ClientToServerEvents {
|
|
29
40
|
"auth": (token: string) => void;
|
|
30
|
-
"filesearch
|
|
31
|
-
"
|
|
32
|
-
"git-pull": (data: GitPullData) => void;
|
|
41
|
+
"filesearch start": (json: string) => void;
|
|
42
|
+
"fs:request": (json: string) => void;
|
|
33
43
|
"send command": (command: string) => void;
|
|
34
44
|
}
|
|
35
45
|
/**
|
|
36
|
-
*
|
|
46
|
+
* Return struct after finishing a Git Clone action
|
|
37
47
|
*
|
|
38
|
-
* @param
|
|
39
|
-
* @param
|
|
48
|
+
* @param folder_name The name of the folder the repo was cloned into
|
|
49
|
+
* @param commit The HEAD commit hash after the clone
|
|
50
|
+
* @param branch The branch that was cloned
|
|
40
51
|
*
|
|
41
52
|
* @internal
|
|
42
53
|
*/
|
|
43
|
-
export interface
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
export interface GitCloneResult {
|
|
55
|
+
folder_name: string;
|
|
56
|
+
commit: string;
|
|
57
|
+
branch: string;
|
|
46
58
|
}
|
|
47
59
|
/**
|
|
48
|
-
* Struct
|
|
60
|
+
* Struct returned after a Git Pull action finishes.
|
|
49
61
|
*
|
|
50
|
-
* @param
|
|
51
|
-
* @param
|
|
52
|
-
* @param
|
|
53
|
-
* @param
|
|
62
|
+
* @param commit The HEAD commit hash after the pull
|
|
63
|
+
* @param branch The branch that was pulled
|
|
64
|
+
* @param files_changed How many files changed (0 when already up to date)
|
|
65
|
+
* @param up_to_date Whether the repo was already up to date
|
|
54
66
|
*
|
|
55
67
|
* @internal
|
|
56
68
|
*/
|
|
57
|
-
export interface
|
|
58
|
-
|
|
59
|
-
url: string;
|
|
69
|
+
export interface GitPullResult {
|
|
70
|
+
commit: string;
|
|
60
71
|
branch: string;
|
|
61
|
-
|
|
72
|
+
files_changed: number;
|
|
73
|
+
up_to_date: boolean;
|
|
62
74
|
}
|
|
63
75
|
/**
|
|
64
|
-
*
|
|
76
|
+
* Payload for an `fs:request`. Sent as a JSON string; `op`-specific fields go
|
|
77
|
+
* alongside `req` and `op`.
|
|
65
78
|
*
|
|
66
|
-
* @
|
|
79
|
+
* @internal
|
|
80
|
+
*/
|
|
81
|
+
export interface FsRequest {
|
|
82
|
+
req: string;
|
|
83
|
+
op: string;
|
|
84
|
+
directory?: string;
|
|
85
|
+
[key: string]: any;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The `fs:result` success envelope; `data` carries the op-specific payload.
|
|
67
89
|
*
|
|
68
90
|
* @internal
|
|
69
91
|
*/
|
|
70
|
-
export interface
|
|
71
|
-
|
|
92
|
+
export interface FsResult<T = any> {
|
|
93
|
+
req: string;
|
|
94
|
+
data?: T;
|
|
72
95
|
}
|
|
73
96
|
/**
|
|
74
|
-
*
|
|
97
|
+
* The `fs:error` envelope. Errors arrive as a separate event from `fs:result`,
|
|
98
|
+
* correlated by `req` (e.g. `code: "auth_required"` / `"auth_invalid"`).
|
|
75
99
|
*
|
|
76
|
-
* @
|
|
77
|
-
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
export interface FsError {
|
|
103
|
+
req: string;
|
|
104
|
+
code: string;
|
|
105
|
+
message: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The parsed `fs:progress` envelope, correlated by `req`. Comes in two shapes:
|
|
109
|
+
* text lines (`kind: "stdout" | "stderr"`, `line`) and structured progress
|
|
110
|
+
* (`kind: "progress"` with `phase`/`current`/`total`/`percent`).
|
|
78
111
|
*
|
|
79
112
|
* @internal
|
|
80
113
|
*/
|
|
81
|
-
export interface
|
|
82
|
-
|
|
83
|
-
|
|
114
|
+
export interface FsProgress {
|
|
115
|
+
req: string;
|
|
116
|
+
kind: "stdout" | "stderr" | "progress" | string;
|
|
117
|
+
line?: string;
|
|
118
|
+
phase?: string;
|
|
119
|
+
current?: number;
|
|
120
|
+
total?: number;
|
|
121
|
+
percent?: number;
|
|
84
122
|
}
|
|
85
123
|
/**
|
|
86
|
-
*
|
|
124
|
+
* Result of a `git-status` op. Repo-specific fields are absent when
|
|
125
|
+
* `is_repo` is false.
|
|
87
126
|
*
|
|
88
|
-
* @
|
|
89
|
-
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
export interface GitStatusResult {
|
|
130
|
+
is_repo: boolean;
|
|
131
|
+
ahead: number;
|
|
132
|
+
behind: number;
|
|
133
|
+
dirty: boolean;
|
|
134
|
+
repo_root?: string;
|
|
135
|
+
branch?: string;
|
|
136
|
+
commit?: string;
|
|
137
|
+
remote_url?: string;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* A single entry in a `list` op result.
|
|
90
141
|
*
|
|
91
142
|
* @internal
|
|
92
143
|
*/
|
|
93
|
-
export interface
|
|
94
|
-
|
|
95
|
-
|
|
144
|
+
export interface FileEntry {
|
|
145
|
+
name: string;
|
|
146
|
+
created: string;
|
|
147
|
+
modified: string;
|
|
148
|
+
mode: string;
|
|
149
|
+
mode_bits: string;
|
|
150
|
+
size: number;
|
|
151
|
+
directory: boolean;
|
|
152
|
+
file: boolean;
|
|
153
|
+
symlink: boolean;
|
|
154
|
+
mime: string;
|
|
155
|
+
child_count?: number;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Options for a `list` op.
|
|
159
|
+
*
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
export interface ListOptions {
|
|
163
|
+
search?: string;
|
|
164
|
+
page?: number;
|
|
165
|
+
perPage?: number;
|
|
166
|
+
sort?: string;
|
|
167
|
+
sortDir?: "asc" | "desc";
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Result of a `list` op: a paginated directory listing.
|
|
171
|
+
*
|
|
172
|
+
* @internal
|
|
173
|
+
*/
|
|
174
|
+
export interface ListResult {
|
|
175
|
+
data: FileEntry[];
|
|
176
|
+
meta: {
|
|
177
|
+
pagination: {
|
|
178
|
+
count: number;
|
|
179
|
+
currentPage: number;
|
|
180
|
+
perPage: number;
|
|
181
|
+
total: number;
|
|
182
|
+
totalPages: number;
|
|
183
|
+
};
|
|
184
|
+
};
|
|
96
185
|
}
|
|
97
186
|
/**
|
|
98
187
|
* An individual filesearch result
|
|
@@ -123,10 +212,33 @@ export interface FilesearchResults {
|
|
|
123
212
|
tooMany: boolean;
|
|
124
213
|
}
|
|
125
214
|
/**
|
|
126
|
-
*
|
|
215
|
+
* Result of an op that just reports success (e.g. `mkdir`).
|
|
216
|
+
*
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
export interface FsOkResult {
|
|
220
|
+
ok: boolean;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Result of a `conflicts` op — the subset of the given paths that already
|
|
224
|
+
* exist / would conflict.
|
|
225
|
+
*
|
|
226
|
+
* @internal
|
|
227
|
+
*/
|
|
228
|
+
export interface ConflictsResult {
|
|
229
|
+
conflicts: string[];
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The websocket type used throughout the pool.
|
|
233
|
+
*
|
|
234
|
+
* The backend no longer speaks Socket.IO, so this is our {@link WispWebSocket}
|
|
235
|
+
* adapter rather than a Socket.IO `Socket`. The {@link ServerToClientEvents}
|
|
236
|
+
* and {@link ClientToServerEvents} interfaces above document the event names
|
|
237
|
+
* but are no longer enforced by the adapter's looser `(...args: any[])` API.
|
|
238
|
+
*
|
|
127
239
|
* @internal
|
|
128
240
|
*/
|
|
129
|
-
export type WispWebsocket =
|
|
241
|
+
export type WispWebsocket = WispWebSocket;
|
|
130
242
|
/**
|
|
131
243
|
* A single worker in the Websocket Pool
|
|
132
244
|
*
|
|
@@ -137,7 +249,9 @@ interface PoolWorker {
|
|
|
137
249
|
socket: WispWebsocket;
|
|
138
250
|
idx: number;
|
|
139
251
|
token: string;
|
|
140
|
-
|
|
252
|
+
url: string;
|
|
253
|
+
connected: boolean;
|
|
254
|
+
busy: boolean;
|
|
141
255
|
done: boolean;
|
|
142
256
|
logger: Logger;
|
|
143
257
|
}
|
|
@@ -149,11 +263,36 @@ interface PoolWorker {
|
|
|
149
263
|
* @internal
|
|
150
264
|
*/
|
|
151
265
|
declare class PoolWorker {
|
|
266
|
+
private intentionalDisconnect;
|
|
267
|
+
private reconnectAttempts;
|
|
268
|
+
private readonly maxReconnectAttempts;
|
|
152
269
|
constructor(pool: WebsocketPool);
|
|
270
|
+
private createSocket;
|
|
271
|
+
private start;
|
|
153
272
|
connect(): Promise<void>;
|
|
273
|
+
private handleDisconnect;
|
|
154
274
|
disconnect(): Promise<void>;
|
|
155
275
|
private processWork;
|
|
156
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* A queued unit of work plus a hook to reject it if it can never run (e.g. the
|
|
279
|
+
* pool has no live workers, or it waited too long to be picked up).
|
|
280
|
+
*
|
|
281
|
+
* @internal
|
|
282
|
+
*/
|
|
283
|
+
interface QueueItem {
|
|
284
|
+
task: (worker: PoolWorker) => Promise<void>;
|
|
285
|
+
reject: (reason?: any) => void;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Fetches fresh websocket details (url + token) for reconnects.
|
|
289
|
+
*
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
export type DetailsProvider = () => Promise<{
|
|
293
|
+
url: string;
|
|
294
|
+
token: string;
|
|
295
|
+
}>;
|
|
157
296
|
/**
|
|
158
297
|
* Struct used to manage a pool of WebSocket workers
|
|
159
298
|
*/
|
|
@@ -161,9 +300,12 @@ export interface WebsocketPool {
|
|
|
161
300
|
workers: PoolWorker[];
|
|
162
301
|
token: string;
|
|
163
302
|
url: string;
|
|
303
|
+
origin: string;
|
|
164
304
|
maxWorkers: number;
|
|
305
|
+
acquireTimeout: number;
|
|
306
|
+
refreshDetails?: DetailsProvider;
|
|
165
307
|
logger: Logger;
|
|
166
|
-
queue:
|
|
308
|
+
queue: QueueItem[];
|
|
167
309
|
}
|
|
168
310
|
/**
|
|
169
311
|
* A pool of {@link PoolWorker}s
|
|
@@ -177,8 +319,10 @@ export interface WebsocketPool {
|
|
|
177
319
|
* @internal
|
|
178
320
|
*/
|
|
179
321
|
export declare class WebsocketPool {
|
|
180
|
-
constructor(url: string, token: string);
|
|
322
|
+
constructor(url: string, token: string, origin: string, refreshDetails?: DetailsProvider);
|
|
181
323
|
getWork(): ((worker: PoolWorker) => Promise<any>) | undefined;
|
|
324
|
+
private allWorkersDone;
|
|
325
|
+
onWorkerDone(): void;
|
|
182
326
|
disconnect(): Promise<void>;
|
|
183
327
|
run(work: (worker: PoolWorker) => Promise<any>): Promise<any>;
|
|
184
328
|
}
|