@ho3einwave/pterodactyl-ts 0.1.0 → 0.1.1

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 CHANGED
@@ -134,7 +134,9 @@ ws.disconnect();
134
134
  import { PteroError, PteroValidationError, PteroRateLimitError } from '@ho3einwave/pterodactyl-ts';
135
135
 
136
136
  try {
137
- await app.users.create({ /* ... */ });
137
+ await app.users.create({
138
+ /* ... */
139
+ });
138
140
  } catch (err) {
139
141
  if (err instanceof PteroValidationError) {
140
142
  console.log(err.fieldErrors); // { email: ['Must be valid email.'] }
package/dist/index.d.mts CHANGED
@@ -1021,10 +1021,10 @@ interface WebSocketEventMap {
1021
1021
  type WebSocketEvent = keyof WebSocketEventMap;
1022
1022
  type Handler<E extends WebSocketEvent> = (...args: WebSocketEventMap[E]) => void;
1023
1023
  interface WebSocketManagerOptions {
1024
- /** Origin used to construct the WebSocket URL. Usually the node FQDN. */
1024
+ /** Full WebSocket URL returned by the API (the `socket` field from credentials). */
1025
+ socket: string;
1026
+ /** Panel origin URL (e.g. "https://panel.example.com"). Sent as the Origin header. */
1025
1027
  origin: string;
1026
- /** Server UUID for the WebSocket path. */
1027
- serverUuid: string;
1028
1028
  /** Function that returns a fresh JWT token. Called on connect and token refresh. */
1029
1029
  getToken: () => Promise<string>;
1030
1030
  /** Maximum reconnect delay in ms. Default: 30000. */
@@ -1038,13 +1038,13 @@ declare class WebSocketManager {
1038
1038
  private reconnectAttempts;
1039
1039
  private reconnectTimer;
1040
1040
  private intentionalClose;
1041
+ private readonly socket;
1041
1042
  private readonly origin;
1042
- private readonly serverUuid;
1043
1043
  private readonly getToken;
1044
1044
  private readonly maxReconnectDelay;
1045
1045
  private readonly autoReconnect;
1046
1046
  constructor(options: WebSocketManagerOptions);
1047
- /** Connect to the WebSocket server. */
1047
+ /** Connect to the WebSocket server. Resolves once authenticated, rejects on error. */
1048
1048
  connect(): Promise<void>;
1049
1049
  /** Disconnect from the WebSocket server. */
1050
1050
  disconnect(): void;
package/dist/index.mjs CHANGED
@@ -497,7 +497,7 @@ var ServerContext = class {
497
497
  await this.http.post(`${this.base}/power`, { signal });
498
498
  }
499
499
  async getWebSocketCredentials() {
500
- return this.http.get(`${this.base}/websocket`);
500
+ return (await (await this.http.raw("GET", `${this.base}/websocket`)).json()).data;
501
501
  }
502
502
  async listStartupVariables() {
503
503
  return (await this.http.getList(`${this.base}/startup`)).data;
@@ -751,37 +751,66 @@ var WebSocketManager = class {
751
751
  reconnectAttempts = 0;
752
752
  reconnectTimer = null;
753
753
  intentionalClose = false;
754
+ socket;
754
755
  origin;
755
- serverUuid;
756
756
  getToken;
757
757
  maxReconnectDelay;
758
758
  autoReconnect;
759
759
  constructor(options) {
760
+ this.socket = options.socket;
760
761
  this.origin = options.origin.replace(/\/+$/, "");
761
- this.serverUuid = options.serverUuid;
762
762
  this.getToken = options.getToken;
763
763
  this.maxReconnectDelay = options.maxReconnectDelay ?? 3e4;
764
764
  this.autoReconnect = options.autoReconnect ?? true;
765
765
  }
766
- /** Connect to the WebSocket server. */
766
+ /** Connect to the WebSocket server. Resolves once authenticated, rejects on error. */
767
767
  async connect() {
768
768
  if (this.ws) return;
769
769
  this.intentionalClose = false;
770
770
  const token = await this.getToken();
771
- const url = `${this.origin.startsWith("https") ? "wss" : "ws"}://${this.origin.replace(/^https?:\/\//, "")}/api/servers/${this.serverUuid}/ws`;
772
- this.ws = new WebSocket(url);
773
- this.ws.onopen = () => {
774
- this.reconnectAttempts = 0;
775
- this.sendAuth(token);
776
- };
777
- this.ws.onmessage = (event) => {
778
- this.handleMessage(event.data);
779
- };
780
- this.ws.onclose = () => {
781
- this.ws = null;
782
- if (!this.intentionalClose && this.autoReconnect) this.scheduleReconnect();
783
- };
784
- this.ws.onerror = () => {};
771
+ return new Promise((resolve, reject) => {
772
+ let settled = false;
773
+ const cleanup = () => {
774
+ this.off("auth success", onAuth);
775
+ this.off("daemon error", onDaemonError);
776
+ };
777
+ const onAuth = () => {
778
+ if (settled) return;
779
+ settled = true;
780
+ cleanup();
781
+ resolve();
782
+ };
783
+ const onDaemonError = (message) => {
784
+ if (settled) return;
785
+ settled = true;
786
+ cleanup();
787
+ reject(/* @__PURE__ */ new Error(`WebSocket authentication failed: ${message}`));
788
+ };
789
+ this.on("auth success", onAuth);
790
+ this.on("daemon error", onDaemonError);
791
+ this.ws = new WebSocket(this.socket, { headers: {
792
+ Authorization: `Bearer ${token}`,
793
+ Origin: this.origin
794
+ } });
795
+ this.ws.onopen = () => {
796
+ this.reconnectAttempts = 0;
797
+ this.sendAuth(token);
798
+ };
799
+ this.ws.onmessage = (event) => {
800
+ this.handleMessage(event.data);
801
+ };
802
+ this.ws.onclose = (event) => {
803
+ this.ws = null;
804
+ if (!settled) {
805
+ settled = true;
806
+ cleanup();
807
+ reject(/* @__PURE__ */ new Error(`WebSocket closed before authentication completed (code: ${event.code}, reason: ${event.reason || "none"})`));
808
+ return;
809
+ }
810
+ if (!this.intentionalClose && this.autoReconnect) this.scheduleReconnect();
811
+ };
812
+ this.ws.onerror = () => {};
813
+ });
785
814
  }
786
815
  /** Disconnect from the WebSocket server. */
787
816
  disconnect() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ho3einwave/pterodactyl-ts",
3
3
  "type": "module",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "description": "Type-safe TypeScript library for the Pterodactyl Panel API. Covers Client API, Application API, and WebSocket API with zero dependencies.",
6
6
  "author": "",
7
7
  "license": "MIT",
@@ -37,11 +37,14 @@
37
37
  "dev": "tsdown --watch",
38
38
  "test": "vitest",
39
39
  "typecheck": "tsc --noEmit",
40
+ "format": "prettier --write .",
41
+ "format:check": "prettier --check .",
40
42
  "prepublishOnly": "bun run build"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@types/node": "^25.0.3",
44
46
  "bumpp": "^10.3.2",
47
+ "prettier": "^3.8.1",
45
48
  "tsdown": "^0.18.1",
46
49
  "typescript": "^5.9.3",
47
50
  "vitest": "^4.0.16"