wispjs 2.3.6 → 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/README.md +1 -1
- 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 +106 -159
- 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 -3
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# WispJS
|
|
2
2
|
<p align="left">
|
|
3
3
|
<a href="https://discord.gg/5JUqZjzmYJ" alt="Discord Invite"><img src="https://img.shields.io/discord/981394195812085770?label=Support&logo=discord&logoColor=white" /></a>
|
|
4
|
-
<a href="https://www.npmjs.com/package/wispjs" alt="NPM Package Link"><img src="https://img.shields.io/npm/v
|
|
4
|
+
<a href="https://www.npmjs.com/package/wispjs" alt="NPM Package Link"><img src="https://img.shields.io/npm/v/wispjs?label=NPM&logo=npm" /></a>
|
|
5
5
|
<a href="https://docs.wispjs.com" alt="Docs Link"><img src="https://img.shields.io/badge/Docs-docs.wispjs.com-blue?logo=readthedocs" /></a>
|
|
6
6
|
</p>
|
|
7
7
|
|
package/dist/wisp_api/index.d.ts
CHANGED
package/dist/wisp_api/index.js
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { WispSocket } from "./index.js";
|
|
2
|
+
import type { ListOptions, ListResult, FilesearchResults, FsOkResult, ConflictsResult } from "./pool.js";
|
|
3
|
+
/**
|
|
4
|
+
* Filesystem operations exposed over the Websocket.
|
|
5
|
+
*
|
|
6
|
+
* `list` runs through the correlated `fs:request` protocol (see
|
|
7
|
+
* {@link WispSocket.request}); `search` uses the dedicated `filesearch start`/
|
|
8
|
+
* `filesearch results` events.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* The new backend also serves plain file read/write/delete/rename over
|
|
12
|
+
* `fs:request`, but those op shapes haven't been captured yet. Until typed
|
|
13
|
+
* wrappers exist here, they're reachable via {@link WispSocket.request}, and
|
|
14
|
+
* the existing HTTP `Filesystem` API covers them too.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export declare class FilesystemSocket {
|
|
19
|
+
private socket;
|
|
20
|
+
constructor(socket: WispSocket);
|
|
21
|
+
/**
|
|
22
|
+
* Lists the contents of a directory (paginated).
|
|
23
|
+
*
|
|
24
|
+
* @param dir The directory to list
|
|
25
|
+
* @param opts Search, pagination, and sort options
|
|
26
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
list(dir: string, opts?: ListOptions, timeout?: number): Promise<ListResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a directory named `name` under `root`.
|
|
33
|
+
*
|
|
34
|
+
* @param root The parent directory the new directory is created in
|
|
35
|
+
* @param name The name of the new directory
|
|
36
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
createDirectory(root: string, name: string, timeout?: number): Promise<FsOkResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Checks which of the given paths already exist / would conflict.
|
|
43
|
+
*
|
|
44
|
+
* @param paths The paths to check
|
|
45
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
conflicts(paths: string[], timeout?: number): Promise<ConflictsResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Searches file contents under a root directory for the given query.
|
|
52
|
+
*
|
|
53
|
+
* @param query The query string to search for
|
|
54
|
+
* @param root The directory to search under
|
|
55
|
+
* @param timeout How long to wait (in ms) for results before timing out
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
search(query: string, root?: string, timeout?: number): Promise<FilesearchResults>;
|
|
60
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem operations exposed over the Websocket.
|
|
3
|
+
*
|
|
4
|
+
* `list` runs through the correlated `fs:request` protocol (see
|
|
5
|
+
* {@link WispSocket.request}); `search` uses the dedicated `filesearch start`/
|
|
6
|
+
* `filesearch results` events.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* The new backend also serves plain file read/write/delete/rename over
|
|
10
|
+
* `fs:request`, but those op shapes haven't been captured yet. Until typed
|
|
11
|
+
* wrappers exist here, they're reachable via {@link WispSocket.request}, and
|
|
12
|
+
* the existing HTTP `Filesystem` API covers them too.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export class FilesystemSocket {
|
|
17
|
+
constructor(socket) {
|
|
18
|
+
this.socket = socket;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Lists the contents of a directory (paginated).
|
|
22
|
+
*
|
|
23
|
+
* @param dir The directory to list
|
|
24
|
+
* @param opts Search, pagination, and sort options
|
|
25
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
26
|
+
*
|
|
27
|
+
* @public
|
|
28
|
+
*/
|
|
29
|
+
async list(dir, opts = {}, timeout = 10000) {
|
|
30
|
+
const params = {
|
|
31
|
+
directory: dir,
|
|
32
|
+
search: opts.search ?? "",
|
|
33
|
+
page: opts.page ?? 1,
|
|
34
|
+
per_page: opts.perPage ?? 100,
|
|
35
|
+
sort: opts.sort ?? "name",
|
|
36
|
+
sort_dir: opts.sortDir ?? "asc",
|
|
37
|
+
};
|
|
38
|
+
return await this.socket.request("list", params, timeout);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a directory named `name` under `root`.
|
|
42
|
+
*
|
|
43
|
+
* @param root The parent directory the new directory is created in
|
|
44
|
+
* @param name The name of the new directory
|
|
45
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
async createDirectory(root, name, timeout = 10000) {
|
|
50
|
+
return await this.socket.request("mkdir", { root, name }, timeout);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Checks which of the given paths already exist / would conflict.
|
|
54
|
+
*
|
|
55
|
+
* @param paths The paths to check
|
|
56
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
async conflicts(paths, timeout = 10000) {
|
|
61
|
+
return await this.socket.request("conflicts", { paths }, timeout);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Searches file contents under a root directory for the given query.
|
|
65
|
+
*
|
|
66
|
+
* @param query The query string to search for
|
|
67
|
+
* @param root The directory to search under
|
|
68
|
+
* @param timeout How long to wait (in ms) for results before timing out
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
async search(query, root = "/garrysmod", timeout = 10000) {
|
|
73
|
+
return await this.socket.runWorker((worker) => {
|
|
74
|
+
const socket = worker.socket;
|
|
75
|
+
const logger = worker.logger;
|
|
76
|
+
logger.log("Running filesearch:", query, root);
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const timeoutObj = setTimeout(() => {
|
|
79
|
+
socket.off("filesearch results");
|
|
80
|
+
logger.error("Rejected filesearch: 'Timeout'");
|
|
81
|
+
reject(new Error("Timeout"));
|
|
82
|
+
}, timeout);
|
|
83
|
+
socket.once("filesearch results", (raw) => {
|
|
84
|
+
clearTimeout(timeoutObj);
|
|
85
|
+
try {
|
|
86
|
+
resolve(JSON.parse(raw));
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
logger.error("Failed to parse filesearch results", raw);
|
|
90
|
+
reject(e);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
socket.emit("filesearch start", JSON.stringify({ query, root }));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { WispSocket } from "./index.js";
|
|
2
|
+
import type { GitPullResult, GitCloneResult, GitStatusResult } from "./pool.js";
|
|
3
|
+
/**
|
|
4
|
+
* Git operations exposed over the Websocket.
|
|
5
|
+
*
|
|
6
|
+
* These run through the backend's correlated `fs:request` protocol (see
|
|
7
|
+
* {@link WispSocket.request}).
|
|
8
|
+
*
|
|
9
|
+
* Authentication: SSH remotes are authenticated server-side via a deploy key
|
|
10
|
+
* configured in the panel. HTTPS remotes can additionally use the GitHub token
|
|
11
|
+
* (`ghToken`) passed to {@link WispInterface} — {@link pull} and {@link clone}
|
|
12
|
+
* automatically retry with it when the remote reports `auth_required`.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export declare class GitSocket {
|
|
17
|
+
private socket;
|
|
18
|
+
constructor(socket: WispSocket);
|
|
19
|
+
/**
|
|
20
|
+
* Runs a git op, retrying once with the configured GitHub token as
|
|
21
|
+
* `authkey` if the remote reports `auth_required` (an HTTPS remote with no
|
|
22
|
+
* credentials). SSH auth is handled server-side, so we only retry this
|
|
23
|
+
* specific case.
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
private withAuthRetry;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the git status of a directory (branch, commit, ahead/behind, dirty).
|
|
30
|
+
*
|
|
31
|
+
* @param dir The full directory path of the repository
|
|
32
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
status(dir: string, timeout?: number): Promise<GitStatusResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Performs a git pull on the given repository directory.
|
|
39
|
+
*
|
|
40
|
+
* @param dir The full directory path to pull
|
|
41
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
pull(dir: string, timeout?: number): Promise<GitPullResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Clones a repository into the given parent directory.
|
|
48
|
+
*
|
|
49
|
+
* @param url The repository URL to clone
|
|
50
|
+
* @param directory The parent directory to clone into
|
|
51
|
+
* @param branch The branch to clone (optional)
|
|
52
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
clone(url: string, directory: string, branch?: string, timeout?: number): Promise<GitCloneResult>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git operations exposed over the Websocket.
|
|
3
|
+
*
|
|
4
|
+
* These run through the backend's correlated `fs:request` protocol (see
|
|
5
|
+
* {@link WispSocket.request}).
|
|
6
|
+
*
|
|
7
|
+
* Authentication: SSH remotes are authenticated server-side via a deploy key
|
|
8
|
+
* configured in the panel. HTTPS remotes can additionally use the GitHub token
|
|
9
|
+
* (`ghToken`) passed to {@link WispInterface} — {@link pull} and {@link clone}
|
|
10
|
+
* automatically retry with it when the remote reports `auth_required`.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export class GitSocket {
|
|
15
|
+
constructor(socket) {
|
|
16
|
+
this.socket = socket;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Runs a git op, retrying once with the configured GitHub token as
|
|
20
|
+
* `authkey` if the remote reports `auth_required` (an HTTPS remote with no
|
|
21
|
+
* credentials). SSH auth is handled server-side, so we only retry this
|
|
22
|
+
* specific case.
|
|
23
|
+
*
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
async withAuthRetry(op, params, timeout) {
|
|
27
|
+
try {
|
|
28
|
+
return await this.socket.request(op, params, timeout);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
if (e?.code === "auth_required" && this.socket.ghToken) {
|
|
32
|
+
return await this.socket.request(op, { ...params, authkey: this.socket.ghToken }, timeout);
|
|
33
|
+
}
|
|
34
|
+
throw e;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets the git status of a directory (branch, commit, ahead/behind, dirty).
|
|
39
|
+
*
|
|
40
|
+
* @param dir The full directory path of the repository
|
|
41
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
async status(dir, timeout = 10000) {
|
|
46
|
+
return await this.socket.request("git-status", { directory: dir }, timeout);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Performs a git pull on the given repository directory.
|
|
50
|
+
*
|
|
51
|
+
* @param dir The full directory path to pull
|
|
52
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
async pull(dir, timeout = 10000) {
|
|
57
|
+
return await this.withAuthRetry("git-pull", { directory: dir }, timeout);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Clones a repository into the given parent directory.
|
|
61
|
+
*
|
|
62
|
+
* @param url The repository URL to clone
|
|
63
|
+
* @param directory The parent directory to clone into
|
|
64
|
+
* @param branch The branch to clone (optional)
|
|
65
|
+
* @param timeout In milliseconds, how long to wait before timing out
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
async clone(url, directory, branch, timeout = 20000) {
|
|
70
|
+
const params = { directory, url };
|
|
71
|
+
if (branch) {
|
|
72
|
+
params.branch = branch;
|
|
73
|
+
}
|
|
74
|
+
return await this.withAuthRetry("git-clone", params, timeout);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { WebsocketPool } from "./pool.js";
|
|
2
|
-
import {
|
|
2
|
+
import { SocketWorker } from "./pool.js";
|
|
3
|
+
import { GitSocket } from "./git.js";
|
|
4
|
+
import { FilesystemSocket } from "./filesystem.js";
|
|
3
5
|
import type { WispAPI } from "../wisp_api/index.js";
|
|
4
6
|
/**
|
|
5
7
|
* The Websocket information returned from the API
|
|
@@ -23,6 +25,8 @@ export interface WispSocket {
|
|
|
23
25
|
ghToken: string | undefined;
|
|
24
26
|
consoleCallbacks: ((message: string) => void)[];
|
|
25
27
|
detailsPreprocessor: WebsocketDetailsPreprocessor | undefined;
|
|
28
|
+
Git: GitSocket;
|
|
29
|
+
Filesystem: FilesystemSocket;
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
32
|
* The primary interface to the Websocket API
|
|
@@ -76,34 +80,49 @@ export declare class WispSocket {
|
|
|
76
80
|
*/
|
|
77
81
|
verifyPool(): Promise<void>;
|
|
78
82
|
/**
|
|
79
|
-
*
|
|
83
|
+
* Runs a job on an available pool worker, handing it the worker's socket
|
|
84
|
+
* and logger. Used for event-based flows (e.g. file search) that don't fit
|
|
85
|
+
* the {@link request} request/response protocol.
|
|
80
86
|
*
|
|
81
|
-
* @param
|
|
82
|
-
* @param timeout How long to wait (in ms) for results before timing out
|
|
87
|
+
* @param work The job to run; receives the worker and returns a Promise
|
|
83
88
|
*
|
|
84
|
-
* @
|
|
89
|
+
* @internal
|
|
85
90
|
*/
|
|
86
|
-
|
|
91
|
+
runWorker<T>(work: (worker: SocketWorker) => Promise<T>): Promise<T>;
|
|
87
92
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* @param dir The full directory path to perform a pull on
|
|
91
|
-
* @param timeout In milliseconds, how long to wait before timing out
|
|
93
|
+
* Generates a short, unique request id for {@link request} correlation.
|
|
92
94
|
*
|
|
93
|
-
* @
|
|
95
|
+
* @internal
|
|
94
96
|
*/
|
|
95
|
-
|
|
97
|
+
private generateReqId;
|
|
96
98
|
/**
|
|
97
|
-
*
|
|
99
|
+
* Issues a correlated `fs:request` to the backend and awaits its outcome.
|
|
100
|
+
*
|
|
101
|
+
* This is the low-level entry point for the git/filesystem protocol. The
|
|
102
|
+
* client emits `fs:request` with a JSON-string payload (`{ req, op, ...params }`),
|
|
103
|
+
* and the backend replies with one of three events, all correlated by `req`
|
|
104
|
+
* and all carrying a JSON-string `args[0]`:
|
|
105
|
+
*
|
|
106
|
+
* - `fs:result` — success; resolves with the parsed `data`
|
|
107
|
+
* - `fs:error` — failure; rejects with an {@link FsError} (plus collected `output`)
|
|
108
|
+
* - `fs:progress` — streaming stdout/stderr/progress lines (collected for error context)
|
|
109
|
+
*
|
|
110
|
+
* Typed convenience wrappers live on {@link GitSocket} ({@link WispSocket.Git})
|
|
111
|
+
* and {@link FilesystemSocket} ({@link WispSocket.Filesystem}); call this
|
|
112
|
+
* directly for ops that don't have a typed wrapper yet.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```js
|
|
116
|
+
* const status = await wisp.socket.request("git-status", { directory: "/garrysmod/addons/acf-3" })
|
|
117
|
+
* ```
|
|
98
118
|
*
|
|
99
|
-
* @param
|
|
100
|
-
* @param
|
|
101
|
-
* @param
|
|
102
|
-
* @param timeout In milliseconds, how long to wait before timing out
|
|
119
|
+
* @param op The operation name (e.g. `git-pull`, `list`)
|
|
120
|
+
* @param params Additional payload fields merged into the request (e.g. `{ directory }`)
|
|
121
|
+
* @param timeout In milliseconds, how long to wait for the result
|
|
103
122
|
*
|
|
104
123
|
* @public
|
|
105
124
|
*/
|
|
106
|
-
|
|
125
|
+
request<T = any>(op: string, params?: Record<string, any>, timeout?: number): Promise<T>;
|
|
107
126
|
/**
|
|
108
127
|
* Sets up the console listener worker
|
|
109
128
|
*
|