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.
@@ -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": "2.3.6",
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,10 +20,12 @@
20
20
  },
21
21
  "homepage": "https://github.com/CFC-Servers/WispJS#readme",
22
22
  "dependencies": {
23
- "socket.io-client": "^4.7.2"
23
+ "strip-ansi": "^7.1.0",
24
+ "ws": "^8.21.0"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/node": "^20.5.4",
28
+ "@types/ws": "^8.18.1",
27
29
  "typedoc": "^0.25.4",
28
30
  "typescript": "^5.3.3"
29
31
  }