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.
@@ -36,4 +36,10 @@ export declare class WispAPI {
36
36
  * @internal
37
37
  */
38
38
  constructor(domain: string, uuid: string, token: string, logger: any);
39
+ /**
40
+ * The panel domain these API calls target.
41
+ *
42
+ * @public
43
+ */
44
+ get domain(): string;
39
45
  }
@@ -38,4 +38,12 @@ export class WispAPI {
38
38
  this.Startup = new StartupAPI(this.core);
39
39
  this.Subusers = new SubusersAPI(this.core);
40
40
  }
41
+ /**
42
+ * The panel domain these API calls target.
43
+ *
44
+ * @public
45
+ */
46
+ get domain() {
47
+ return this.core.domain;
48
+ }
41
49
  }
@@ -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 { FilesearchResults } from "./pool";
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
- * Searches all file contents for the given query
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 query The query string to search for
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
- * @public
89
+ * @internal
85
90
  */
86
- filesearch(query: string, timeout?: number): Promise<FilesearchResults>;
91
+ runWorker<T>(work: (worker: SocketWorker) => Promise<T>): Promise<T>;
87
92
  /**
88
- * Performs a git pull operation on the given directory
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
- * @public
95
+ * @internal
94
96
  */
95
- gitPull(dir: string, useAuth?: boolean, timeout?: number): Promise<any>;
97
+ private generateReqId;
96
98
  /**
97
- * Clones a new Repo to the given directory
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 url The HTTPS URL of the repository
100
- * @param dir The full path of the directory to clone the repository to
101
- * @param branch The branch of the repository to clone
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
- gitClone(url: string, dir: string, branch: string, timeout?: number): Promise<any>;
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
  *