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
package/dist/wisp_socket/pool.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { WispWebSocket } from "./ws_adapter.js";
|
|
2
2
|
const WISP_DEBUG = process.env.WISP_DEBUG === "true";
|
|
3
3
|
/**
|
|
4
4
|
* A single Worker within a {@link WebsocketPool}
|
|
@@ -9,17 +9,16 @@ const WISP_DEBUG = process.env.WISP_DEBUG === "true";
|
|
|
9
9
|
*/
|
|
10
10
|
class PoolWorker {
|
|
11
11
|
constructor(pool) {
|
|
12
|
+
this.intentionalDisconnect = false;
|
|
13
|
+
this.reconnectAttempts = 0;
|
|
14
|
+
this.maxReconnectAttempts = 3;
|
|
12
15
|
this.pool = pool;
|
|
13
|
-
this.
|
|
16
|
+
this.connected = false;
|
|
17
|
+
this.busy = false;
|
|
14
18
|
this.done = false;
|
|
15
19
|
this.idx = pool.workers.length;
|
|
16
20
|
this.token = pool.token;
|
|
17
|
-
this.
|
|
18
|
-
forceNew: true,
|
|
19
|
-
transports: ["websocket"],
|
|
20
|
-
addTrailingSlash: true,
|
|
21
|
-
autoConnect: false
|
|
22
|
-
});
|
|
21
|
+
this.url = pool.url;
|
|
23
22
|
const logPrefix = `[Worker #${this.idx}]`;
|
|
24
23
|
this.logger = {
|
|
25
24
|
log: (...args) => console.log(logPrefix, args),
|
|
@@ -30,7 +29,22 @@ class PoolWorker {
|
|
|
30
29
|
console.debug(logPrefix, args);
|
|
31
30
|
}
|
|
32
31
|
};
|
|
33
|
-
this.
|
|
32
|
+
this.start();
|
|
33
|
+
this.processWork();
|
|
34
|
+
}
|
|
35
|
+
createSocket() {
|
|
36
|
+
this.socket = new WispWebSocket(this.url, {
|
|
37
|
+
origin: this.pool.origin
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
start() {
|
|
41
|
+
this.createSocket();
|
|
42
|
+
this.connect()
|
|
43
|
+
.then(() => this.logger.log("Connection established"))
|
|
44
|
+
.catch((err) => {
|
|
45
|
+
this.logger.error("Connection failed", err);
|
|
46
|
+
this.handleDisconnect("connection failure");
|
|
47
|
+
});
|
|
34
48
|
}
|
|
35
49
|
connect() {
|
|
36
50
|
const socket = this.socket;
|
|
@@ -40,11 +54,10 @@ class PoolWorker {
|
|
|
40
54
|
return new Promise((resolve, reject) => {
|
|
41
55
|
const timeout = setTimeout(() => {
|
|
42
56
|
logger.error("Socket didn't connect in time");
|
|
43
|
-
reject("Connection Timeout");
|
|
57
|
+
reject(new Error("Connection Timeout"));
|
|
44
58
|
}, 10000);
|
|
45
59
|
socket.on("connect", () => {
|
|
46
|
-
logger.log("Connected to WebSocket");
|
|
47
|
-
logger.log("Emitting:", "auth", this.token);
|
|
60
|
+
logger.log("Connected to WebSocket, authenticating");
|
|
48
61
|
socket.emit("auth", this.token);
|
|
49
62
|
});
|
|
50
63
|
socket.on("error", (reason) => {
|
|
@@ -52,28 +65,65 @@ class PoolWorker {
|
|
|
52
65
|
});
|
|
53
66
|
socket.on("connect_error", (error) => {
|
|
54
67
|
logger.error(`WebSocket Connect error: ${error.toString()}`);
|
|
55
|
-
this.done = true;
|
|
56
68
|
clearTimeout(timeout);
|
|
57
|
-
reject(
|
|
69
|
+
reject(error);
|
|
58
70
|
});
|
|
59
71
|
socket.on("disconnect", (reason) => {
|
|
60
72
|
logger.log(`Disconnected from WebSocket: ${reason}`);
|
|
73
|
+
this.connected = false;
|
|
74
|
+
this.handleDisconnect(reason);
|
|
61
75
|
});
|
|
62
|
-
socket.on("
|
|
76
|
+
socket.on("auth success", () => {
|
|
63
77
|
logger.log("Auth success");
|
|
64
|
-
this.
|
|
78
|
+
this.reconnectAttempts = 0;
|
|
79
|
+
this.connected = true;
|
|
65
80
|
clearTimeout(timeout);
|
|
66
81
|
resolve();
|
|
67
82
|
});
|
|
68
83
|
socket.connect();
|
|
69
84
|
});
|
|
70
85
|
}
|
|
86
|
+
// Recovers from an unexpected disconnect by reconnecting with a freshly
|
|
87
|
+
// fetched token (the JWT is short-lived). After maxReconnectAttempts the
|
|
88
|
+
// worker is marked dead so the pool stops handing it work.
|
|
89
|
+
async handleDisconnect(reason) {
|
|
90
|
+
this.connected = false;
|
|
91
|
+
if (this.intentionalDisconnect || this.done) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
95
|
+
this.logger.error(`Giving up after ${this.reconnectAttempts} reconnect attempts (${reason})`);
|
|
96
|
+
this.done = true;
|
|
97
|
+
this.pool.onWorkerDone();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.reconnectAttempts++;
|
|
101
|
+
const backoff = Math.min(1000 * this.reconnectAttempts, 5000);
|
|
102
|
+
this.logger.log(`Reconnecting (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}) in ${backoff}ms`);
|
|
103
|
+
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
104
|
+
if (this.intentionalDisconnect || this.done) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (this.pool.refreshDetails) {
|
|
108
|
+
try {
|
|
109
|
+
const details = await this.pool.refreshDetails();
|
|
110
|
+
this.url = details.url;
|
|
111
|
+
this.token = details.token;
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
this.logger.error("Failed to refresh websocket details for reconnect", e);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
this.start();
|
|
118
|
+
}
|
|
71
119
|
disconnect() {
|
|
72
|
-
this.
|
|
73
|
-
|
|
120
|
+
this.intentionalDisconnect = true;
|
|
121
|
+
this.connected = false;
|
|
122
|
+
return new Promise((resolve) => {
|
|
74
123
|
const timeout = setTimeout(() => {
|
|
75
124
|
this.logger.error("Socket didn't disconnect in time");
|
|
76
|
-
|
|
125
|
+
this.done = true;
|
|
126
|
+
resolve();
|
|
77
127
|
}, 5000);
|
|
78
128
|
this.socket.once("disconnect", () => {
|
|
79
129
|
this.done = true;
|
|
@@ -85,13 +135,13 @@ class PoolWorker {
|
|
|
85
135
|
}
|
|
86
136
|
async processWork() {
|
|
87
137
|
while (!this.done) {
|
|
88
|
-
if (!this.
|
|
138
|
+
if (!this.connected || this.busy) {
|
|
89
139
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
90
140
|
continue;
|
|
91
141
|
}
|
|
92
142
|
const work = this.pool.getWork();
|
|
93
143
|
if (work) {
|
|
94
|
-
this.
|
|
144
|
+
this.busy = true;
|
|
95
145
|
try {
|
|
96
146
|
this.logger.debug("Running my work");
|
|
97
147
|
await work(this);
|
|
@@ -102,7 +152,7 @@ class PoolWorker {
|
|
|
102
152
|
this.logger.error(e);
|
|
103
153
|
}
|
|
104
154
|
finally {
|
|
105
|
-
this.
|
|
155
|
+
this.busy = false;
|
|
106
156
|
}
|
|
107
157
|
}
|
|
108
158
|
else {
|
|
@@ -123,11 +173,15 @@ class PoolWorker {
|
|
|
123
173
|
* @internal
|
|
124
174
|
*/
|
|
125
175
|
export class WebsocketPool {
|
|
126
|
-
constructor(url, token) {
|
|
176
|
+
constructor(url, token, origin, refreshDetails) {
|
|
127
177
|
const envMaxWorkers = process.env.WISP_MAX_WORKERS;
|
|
128
178
|
this.maxWorkers = envMaxWorkers ? parseInt(envMaxWorkers) : 5;
|
|
179
|
+
const envAcquire = process.env.WISP_ACQUIRE_TIMEOUT;
|
|
180
|
+
this.acquireTimeout = envAcquire ? parseInt(envAcquire) : 60000;
|
|
129
181
|
this.token = token;
|
|
130
182
|
this.url = url;
|
|
183
|
+
this.origin = origin;
|
|
184
|
+
this.refreshDetails = refreshDetails;
|
|
131
185
|
const logPrefix = "[Pool]";
|
|
132
186
|
this.logger = {
|
|
133
187
|
log: (...args) => console.log(logPrefix, args),
|
|
@@ -146,7 +200,22 @@ export class WebsocketPool {
|
|
|
146
200
|
}
|
|
147
201
|
}
|
|
148
202
|
getWork() {
|
|
149
|
-
return this.queue.shift();
|
|
203
|
+
return this.queue.shift()?.task;
|
|
204
|
+
}
|
|
205
|
+
allWorkersDone() {
|
|
206
|
+
return this.workers.length > 0 && this.workers.every((worker) => worker.done);
|
|
207
|
+
}
|
|
208
|
+
// Called by a worker when it gives up permanently. If no workers remain,
|
|
209
|
+
// queued work can never run, so reject it instead of letting it hang.
|
|
210
|
+
onWorkerDone() {
|
|
211
|
+
if (!this.allWorkersDone()) {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
this.logger.error("All workers are dead - draining queued work");
|
|
215
|
+
const error = new Error("WebsocketPool has no live workers");
|
|
216
|
+
while (this.queue.length > 0) {
|
|
217
|
+
this.queue.shift()?.reject(error);
|
|
218
|
+
}
|
|
150
219
|
}
|
|
151
220
|
async disconnect() {
|
|
152
221
|
this.logger.log("Disconnecting all workers...");
|
|
@@ -154,17 +223,47 @@ export class WebsocketPool {
|
|
|
154
223
|
this.logger.log("All workers disconnected");
|
|
155
224
|
}
|
|
156
225
|
async run(work) {
|
|
157
|
-
return new Promise(
|
|
158
|
-
this.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
if (this.allWorkersDone()) {
|
|
228
|
+
reject(new Error("WebsocketPool has no live workers"));
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
let settled = false;
|
|
232
|
+
const item = {
|
|
233
|
+
task: async (worker) => {
|
|
234
|
+
if (settled) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
settled = true;
|
|
238
|
+
clearTimeout(acquireTimer);
|
|
239
|
+
try {
|
|
240
|
+
const result = await work(worker);
|
|
241
|
+
resolve(result);
|
|
242
|
+
}
|
|
243
|
+
catch (e) {
|
|
244
|
+
worker.logger.error("Failed to run a job!");
|
|
245
|
+
reject(e);
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
reject: (reason) => {
|
|
249
|
+
if (settled) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
settled = true;
|
|
253
|
+
clearTimeout(acquireTimer);
|
|
254
|
+
reject(reason);
|
|
162
255
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
256
|
+
};
|
|
257
|
+
// Backstop so work can't sit in the queue forever if every worker
|
|
258
|
+
// is wedged. Worker death is handled separately by onWorkerDone.
|
|
259
|
+
const acquireTimer = setTimeout(() => {
|
|
260
|
+
const idx = this.queue.indexOf(item);
|
|
261
|
+
if (idx !== -1) {
|
|
262
|
+
this.queue.splice(idx, 1);
|
|
166
263
|
}
|
|
167
|
-
|
|
264
|
+
item.reject(new Error(`Timed out waiting for an available worker after ${this.acquireTimeout}ms`));
|
|
265
|
+
}, this.acquireTimeout);
|
|
266
|
+
this.queue.push(item);
|
|
168
267
|
});
|
|
169
268
|
}
|
|
170
269
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for the {@link WispWebSocket} adapter
|
|
3
|
+
*
|
|
4
|
+
* @param origin The value to send as the `Origin` header during the upgrade
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export interface WsAdapterOptions {
|
|
9
|
+
origin?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A thin adapter that exposes a Socket.IO-like event API over a plain `ws`
|
|
13
|
+
* WebSocket.
|
|
14
|
+
*
|
|
15
|
+
* The new backend speaks a simple JSON envelope rather than the Socket.IO /
|
|
16
|
+
* Engine.IO framing:
|
|
17
|
+
*
|
|
18
|
+
* ```json
|
|
19
|
+
* { "event": "console output", "args": ["...line..."] }
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* `args` is omitted entirely when an event carries no payload
|
|
23
|
+
* (e.g. `{ "event": "auth success" }`).
|
|
24
|
+
*
|
|
25
|
+
* This class translates between that envelope and the `.on/.once/.off/.emit`
|
|
26
|
+
* surface the rest of the codebase already uses, so the calling code barely
|
|
27
|
+
* changes.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* We *compose* an EventEmitter instead of extending one on purpose: extending
|
|
31
|
+
* it would mean overriding `emit()`, which EventEmitter also calls internally
|
|
32
|
+
* (e.g. the `newListener` event) — so every `.on()` would try to send a frame
|
|
33
|
+
* to the server. Composition keeps "emit to the wire" and "fire local
|
|
34
|
+
* listeners" cleanly separate.
|
|
35
|
+
*
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare class WispWebSocket {
|
|
39
|
+
private url;
|
|
40
|
+
private origin?;
|
|
41
|
+
private ws?;
|
|
42
|
+
private emitter;
|
|
43
|
+
private outgoingListener?;
|
|
44
|
+
constructor(url: string, opts?: WsAdapterOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Opens the underlying WebSocket and wires up frame translation.
|
|
47
|
+
*/
|
|
48
|
+
connect(): this;
|
|
49
|
+
/**
|
|
50
|
+
* Sends an event to the server as a `{ event, args }` JSON frame.
|
|
51
|
+
*
|
|
52
|
+
* @remarks
|
|
53
|
+
* Unlike EventEmitter.emit, this does NOT fire local listeners — it writes
|
|
54
|
+
* to the socket. Incoming frames fire local listeners via the internal
|
|
55
|
+
* emitter.
|
|
56
|
+
*/
|
|
57
|
+
emit(event: string, ...args: any[]): boolean;
|
|
58
|
+
on(event: string, listener: (...args: any[]) => void): this;
|
|
59
|
+
once(event: string, listener: (...args: any[]) => void): this;
|
|
60
|
+
/**
|
|
61
|
+
* Removes a specific listener, or — matching Socket.IO's behaviour — all
|
|
62
|
+
* listeners for an event when no listener is given.
|
|
63
|
+
*/
|
|
64
|
+
off(event: string, listener?: (...args: any[]) => void): this;
|
|
65
|
+
removeAllListeners(event?: string): this;
|
|
66
|
+
/**
|
|
67
|
+
* Registers a callback invoked for every outgoing emit (parity with
|
|
68
|
+
* Socket.IO's `onAnyOutgoing`, used for logging).
|
|
69
|
+
*/
|
|
70
|
+
onAnyOutgoing(listener: (...args: any[]) => void): this;
|
|
71
|
+
disconnect(): this;
|
|
72
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import WebSocket from "ws";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
/**
|
|
4
|
+
* A thin adapter that exposes a Socket.IO-like event API over a plain `ws`
|
|
5
|
+
* WebSocket.
|
|
6
|
+
*
|
|
7
|
+
* The new backend speaks a simple JSON envelope rather than the Socket.IO /
|
|
8
|
+
* Engine.IO framing:
|
|
9
|
+
*
|
|
10
|
+
* ```json
|
|
11
|
+
* { "event": "console output", "args": ["...line..."] }
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* `args` is omitted entirely when an event carries no payload
|
|
15
|
+
* (e.g. `{ "event": "auth success" }`).
|
|
16
|
+
*
|
|
17
|
+
* This class translates between that envelope and the `.on/.once/.off/.emit`
|
|
18
|
+
* surface the rest of the codebase already uses, so the calling code barely
|
|
19
|
+
* changes.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* We *compose* an EventEmitter instead of extending one on purpose: extending
|
|
23
|
+
* it would mean overriding `emit()`, which EventEmitter also calls internally
|
|
24
|
+
* (e.g. the `newListener` event) — so every `.on()` would try to send a frame
|
|
25
|
+
* to the server. Composition keeps "emit to the wire" and "fire local
|
|
26
|
+
* listeners" cleanly separate.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export class WispWebSocket {
|
|
31
|
+
constructor(url, opts = {}) {
|
|
32
|
+
this.emitter = new EventEmitter();
|
|
33
|
+
this.url = url;
|
|
34
|
+
this.origin = opts.origin;
|
|
35
|
+
// The pool registers a handful of listeners per worker; silence the
|
|
36
|
+
// default 10-listener warning.
|
|
37
|
+
this.emitter.setMaxListeners(0);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Opens the underlying WebSocket and wires up frame translation.
|
|
41
|
+
*/
|
|
42
|
+
connect() {
|
|
43
|
+
const ws = new WebSocket(this.url, this.origin ? { origin: this.origin } : undefined);
|
|
44
|
+
this.ws = ws;
|
|
45
|
+
// Map ws lifecycle onto the Socket.IO-style events the pool listens for
|
|
46
|
+
ws.on("open", () => this.emitter.emit("connect"));
|
|
47
|
+
ws.on("close", (code, reason) => {
|
|
48
|
+
this.emitter.emit("disconnect", reason?.toString() || `code ${code}`);
|
|
49
|
+
});
|
|
50
|
+
ws.on("error", (err) => this.emitter.emit("connect_error", err));
|
|
51
|
+
ws.on("message", (data, isBinary) => {
|
|
52
|
+
if (isBinary)
|
|
53
|
+
return;
|
|
54
|
+
let frame;
|
|
55
|
+
try {
|
|
56
|
+
frame = JSON.parse(data.toString());
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return; // ignore anything that isn't our JSON envelope
|
|
60
|
+
}
|
|
61
|
+
const event = frame.event;
|
|
62
|
+
if (!event)
|
|
63
|
+
return;
|
|
64
|
+
const args = frame.args ?? [];
|
|
65
|
+
// EventEmitter throws if "error" is emitted with no listener; guard it.
|
|
66
|
+
if (event === "error" && this.emitter.listenerCount("error") === 0) {
|
|
67
|
+
console.error("[ws] server error frame:", ...args);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
this.emitter.emit(event, ...args);
|
|
71
|
+
});
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Sends an event to the server as a `{ event, args }` JSON frame.
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* Unlike EventEmitter.emit, this does NOT fire local listeners — it writes
|
|
79
|
+
* to the socket. Incoming frames fire local listeners via the internal
|
|
80
|
+
* emitter.
|
|
81
|
+
*/
|
|
82
|
+
emit(event, ...args) {
|
|
83
|
+
this.outgoingListener?.(event, ...args);
|
|
84
|
+
const frame = JSON.stringify(args.length ? { event, args } : { event });
|
|
85
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
86
|
+
this.ws.send(frame);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
console.error(`[ws] dropped outgoing "${event}" — socket not open`);
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
on(event, listener) {
|
|
94
|
+
this.emitter.on(event, listener);
|
|
95
|
+
return this;
|
|
96
|
+
}
|
|
97
|
+
once(event, listener) {
|
|
98
|
+
this.emitter.once(event, listener);
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Removes a specific listener, or — matching Socket.IO's behaviour — all
|
|
103
|
+
* listeners for an event when no listener is given.
|
|
104
|
+
*/
|
|
105
|
+
off(event, listener) {
|
|
106
|
+
if (listener) {
|
|
107
|
+
this.emitter.off(event, listener);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.emitter.removeAllListeners(event);
|
|
111
|
+
}
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
removeAllListeners(event) {
|
|
115
|
+
this.emitter.removeAllListeners(event);
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Registers a callback invoked for every outgoing emit (parity with
|
|
120
|
+
* Socket.IO's `onAnyOutgoing`, used for logging).
|
|
121
|
+
*/
|
|
122
|
+
onAnyOutgoing(listener) {
|
|
123
|
+
this.outgoingListener = listener;
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
disconnect() {
|
|
127
|
+
this.ws?.close();
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wispjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A package for interacting with Wisp-based server panels",
|
|
6
6
|
"main": "dist/wisp.js",
|
|
7
7
|
"types": "dist/wisp.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "tsc",
|
|
10
|
-
"build-docs": "typedoc wisp.ts wisp_api/index.ts wisp_socket/index.ts wisp_api/apis/*"
|
|
10
|
+
"build-docs": "typedoc wisp.ts wisp_api/index.ts wisp_socket/index.ts wisp_socket/git.ts wisp_socket/filesystem.ts wisp_api/apis/*"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
@@ -20,11 +20,12 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/CFC-Servers/WispJS#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
"
|
|
23
|
+
"strip-ansi": "^7.1.0",
|
|
24
|
+
"ws": "^8.21.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^20.5.4",
|
|
28
|
+
"@types/ws": "^8.18.1",
|
|
28
29
|
"typedoc": "^0.25.4",
|
|
29
30
|
"typescript": "^5.3.3"
|
|
30
31
|
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
name: Deploy
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
inputs:
|
|
6
|
-
version_tag:
|
|
7
|
-
description: "Version tag for the package"
|
|
8
|
-
required: true
|
|
9
|
-
|
|
10
|
-
jobs:
|
|
11
|
-
build:
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v4
|
|
15
|
-
|
|
16
|
-
- uses: actions/setup-node@v4
|
|
17
|
-
with:
|
|
18
|
-
node-version: 18
|
|
19
|
-
|
|
20
|
-
- name: Update package version
|
|
21
|
-
run: |
|
|
22
|
-
version=${{ inputs.version_tag }}
|
|
23
|
-
npm version $version --no-git-tag-version
|
|
24
|
-
|
|
25
|
-
- name: Install packages
|
|
26
|
-
run: |
|
|
27
|
-
npm ci
|
|
28
|
-
|
|
29
|
-
- name: Build
|
|
30
|
-
run: |
|
|
31
|
-
npm run build
|
|
32
|
-
|
|
33
|
-
- name: Generate Docs
|
|
34
|
-
run: |
|
|
35
|
-
npm run build-docs
|
|
36
|
-
mv docs ../docs_wip
|
|
37
|
-
|
|
38
|
-
- name: Remove Non-distributables
|
|
39
|
-
run: |
|
|
40
|
-
rm .gitignore
|
|
41
|
-
rm tsconfig.json
|
|
42
|
-
rm wisp.ts
|
|
43
|
-
rm -rf wisp_api wisp_socket .github
|
|
44
|
-
|
|
45
|
-
- name: Publish
|
|
46
|
-
uses: JS-DevTools/npm-publish@v3
|
|
47
|
-
with:
|
|
48
|
-
token: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
|
49
|
-
|
|
50
|
-
- name: Configure Git User
|
|
51
|
-
run: |
|
|
52
|
-
git config user.name github-actions
|
|
53
|
-
git config user.email github-actions@github.com
|
|
54
|
-
|
|
55
|
-
- name: Push package version change
|
|
56
|
-
run: |
|
|
57
|
-
git add package.json
|
|
58
|
-
git add package-lock.json
|
|
59
|
-
git commit -m "Update package.json version to: ${{ inputs.version_tag }}" && \
|
|
60
|
-
git push --force-with-lease origin main || \
|
|
61
|
-
echo "Version tag unchanaged"
|
|
62
|
-
|
|
63
|
-
- name: Push new tag
|
|
64
|
-
run: |
|
|
65
|
-
git tag "${{ inputs.version_tag }}"
|
|
66
|
-
git push --tags
|
|
67
|
-
|
|
68
|
-
- name: Publish Docs
|
|
69
|
-
run: |
|
|
70
|
-
# Delete everything except .git
|
|
71
|
-
find . -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
|
|
72
|
-
|
|
73
|
-
# Move the docs back and commit only them
|
|
74
|
-
mv ../docs_wip docs
|
|
75
|
-
git add .
|
|
76
|
-
git commit -m "Update Docs for version: ${{ inputs.version_tag }}"
|
|
77
|
-
git push --force origin HEAD:docs
|
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
|
|
6
|
-
"outDir": "./dist/",
|
|
7
|
-
"declaration": true,
|
|
8
|
-
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"forceConsistentCasingInFileNames": true,
|
|
11
|
-
|
|
12
|
-
"strict": true,
|
|
13
|
-
"skipLibCheck": true,
|
|
14
|
-
"moduleResolution": "node"
|
|
15
|
-
},
|
|
16
|
-
"include": ["*.ts"],
|
|
17
|
-
"exclude": ["node_modules"]
|
|
18
|
-
}
|
|
19
|
-
|
package/wisp.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { WispAPI } from "./wisp_api/index.js";
|
|
2
|
-
import { WispSocket } from "./wisp_socket/index.js";
|
|
3
|
-
|
|
4
|
-
export interface WispInterface {
|
|
5
|
-
socket: WispSocket;
|
|
6
|
-
api: WispAPI;
|
|
7
|
-
logger: any;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* The primary Wisp Interface, exposing interactions with both the HTTP and Websockets API
|
|
12
|
-
*
|
|
13
|
-
* @param domain The Domain of the Pterodactyl/Wisp panel (e.g. `my.gamepanel.gg`)
|
|
14
|
-
* @param uuid The UUID of the server to reference in all API requests
|
|
15
|
-
* @param token The panel API token to use for authorization
|
|
16
|
-
* @param ghPAT The Github Personal Access Token used for Cloning/Pulling of private repositories. This may be omitted if you do not need to interact with private repositories
|
|
17
|
-
*
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export class WispInterface {
|
|
21
|
-
constructor(domain: string, uuid: string, token: string, ghPAT?: string) {
|
|
22
|
-
this.logger = {
|
|
23
|
-
info: (msg: any) => {
|
|
24
|
-
console.log(msg);
|
|
25
|
-
},
|
|
26
|
-
error: (msg: string) => {
|
|
27
|
-
console.error(msg);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
this.api = new WispAPI(domain, uuid, token, this.logger);
|
|
32
|
-
this.socket = new WispSocket(this.logger, this.api, ghPAT);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Manually disconnects from the Websocket connection(s)
|
|
37
|
-
*
|
|
38
|
-
* @public
|
|
39
|
-
*/
|
|
40
|
-
async disconnect() {
|
|
41
|
-
await this.socket.disconnect();
|
|
42
|
-
}
|
|
43
|
-
}
|