erlc-api 3.3.2-a → 3.3.3

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
@@ -30,53 +30,60 @@ bun add erlc-api
30
30
 
31
31
  ### Initialization
32
32
 
33
- You can use the library with or without a `Global Token` (required only for large-scale applications).
33
+ You can initialize the client with your `Server Key` so every server request can reuse it automatically. A `Global Token` is optional and only required for large-scale applications.
34
34
 
35
35
  **JavaScript**
36
36
  ```javascript
37
37
  const erlc = require("erlc-api");
38
38
 
39
- // Simple initialization (Recommended for most users)
40
- const client = new erlc.Client();
39
+ const client = new erlc.Client({
40
+ serverToken: "your-server-key-here",
41
+ // globalToken: "your-global-token-here", // Optional, for large apps
42
+ });
43
+
44
+ await client.ready;
41
45
 
42
- // Or with Global Token (For Large Apps)
43
- // const client = new erlc.Client({ globalToken: "..." });
46
+ if (!client.connected) {
47
+ console.error("Could not connect:", client.connectionError.message);
48
+ }
44
49
  ```
45
50
 
46
51
  **TypeScript**
47
52
  ```typescript
48
- import { Client, getServer } from "erlc-api";
53
+ import { Client } from "erlc-api";
49
54
 
50
- const client = new Client();
55
+ const client = new Client({
56
+ serverToken: "your-server-key-here",
57
+ });
58
+
59
+ await client.ready;
51
60
  ```
52
61
 
53
62
  ---
54
63
 
55
64
  ## 📖 Usage Examples
56
65
 
57
- Make sure to have your `Server Key` ready (get it from your private server settings in ER:LC).
66
+ Make sure to have your `Server Key` ready (get it from your private server settings in ER:LC). When the key is configured in `Client`, you do not need to pass it again on every request.
58
67
 
59
68
  ### 🖥️ Server Information
60
69
 
61
70
  ```javascript
62
- const serverToken = "your-server-key-here";
63
-
64
71
  // Get server status
65
- const server = await erlc.getServer(serverToken);
72
+ const server = await client.getServer();
66
73
  console.log(`Server: ${server.Name} | Players: ${server.CurrentPlayers}/${server.MaxPlayers}`);
67
74
 
68
75
  // Get connected players
69
- const players = await erlc.getPlayers(serverToken);
76
+ const players = await client.getPlayers();
70
77
  console.table(players); // Shows name, ID, permission, and team
71
78
 
72
79
  // Get vehicles on the map
73
- const vehicles = await erlc.getVehicles(serverToken);
80
+ const vehicles = await client.getVehicles();
74
81
 
75
82
  // Get emergency calls
76
- const emergencyCalls = await erlc.getEmergencyCalls(serverToken);
83
+ const emergencyCalls = await client.getEmergencyCalls();
77
84
 
78
85
  // Fetch server info with v2 include flags in one request
79
- const fullServer = await erlc.getServer(serverToken, {
86
+ const fullServer = await client.getServer({
80
87
  players: true,
81
88
  staff: true,
82
89
  emergencyCalls: true,
@@ -89,29 +96,29 @@ Access your server's activity history:
89
96
 
90
97
  ```javascript
91
98
  // Join/Leave Logs
92
- const joinLogs = await erlc.getJoinLogs(serverToken);
99
+ const joinLogs = await client.getJoinLogs();
93
100
 
94
101
  // Kill Logs (Killfeed)
95
- const killLogs = await erlc.getKillLogs(serverToken);
102
+ const killLogs = await client.getKillLogs();
96
103
 
97
104
  // Command Logs
98
- const commandLogs = await erlc.getCommandLogs(serverToken);
105
+ const commandLogs = await client.getCommandLogs();
99
106
 
100
107
  // Mod Call Logs
101
- const modCalls = await erlc.getModcallLogs(serverToken);
108
+ const modCalls = await client.getModcallLogs();
102
109
  ```
103
110
 
104
111
  ### 🛠️ Management & Administration
105
112
 
106
113
  ```javascript
107
114
  // Get Ban List
108
- const bans = await erlc.getBans(serverToken);
115
+ const bans = await client.getBans();
109
116
 
110
117
  // Get Server Staff
111
- const staff = await erlc.getStaff(serverToken);
118
+ const staff = await client.getStaff();
112
119
 
113
120
  // Get Queue
114
- const queue = await erlc.getQueue(serverToken);
121
+ const queue = await client.getQueue();
115
122
  ```
116
123
 
117
124
  ### ⚡ Run Command
@@ -119,10 +126,19 @@ const queue = await erlc.getQueue(serverToken);
119
126
  Execute commands directly from your code:
120
127
 
121
128
  ```javascript
122
- const command = await erlc.runCommand(serverToken, ":announce This is an API test!");
129
+ const command = await client.runCommand(":announce This is an API test!");
123
130
  console.log(command); // Returns true if successful
124
131
  ```
125
132
 
133
+ ### Manual Token Usage
134
+
135
+ You can still pass the server token directly if you prefer the older style:
136
+
137
+ ```javascript
138
+ const server = await erlc.getServer("your-server-key-here");
139
+ const players = await erlc.getPlayers("your-server-key-here");
140
+ ```
141
+
126
142
  ---
127
143
 
128
144
  ## ⚠️ Error Handling
@@ -131,7 +147,8 @@ The library throws descriptive errors. You should wrap your calls in `try/catch`
131
147
 
132
148
  ```javascript
133
149
  try {
134
- const data = await erlc.getServer("invalid-token");
150
+ const client = new erlc.Client({ serverToken: "invalid-token" });
151
+ await client.connect();
135
152
  } catch (error) {
136
153
  console.error(error.message); // e.g., "Forbidden: Access denied..."
137
154
  }
package/README_ES.md CHANGED
@@ -30,57 +30,64 @@ bun add erlc-api
30
30
 
31
31
  ### Inicialización
32
32
 
33
- Puedes usar la librería con o sin un `Global Token` (requerido solo para aplicaciones a gran escala).
33
+ Puedes iniciar el cliente con tu `Server Key` para reutilizarla automáticamente en todas las peticiones del servidor. El `Global Token` es opcional y solo se requiere para aplicaciones a gran escala.
34
34
 
35
35
  **JavaScript**
36
36
 
37
37
  ```javascript
38
38
  const erlc = require("erlc-api");
39
39
 
40
- // Inicialización simple (Recomendada para la mayoría)
41
- const client = new erlc.Client();
40
+ const client = new erlc.Client({
41
+ serverToken: "tu-server-key-aqui",
42
+ // globalToken: "tu-global-token-aqui", // Opcional, para apps grandes
43
+ });
44
+
45
+ await client.ready;
42
46
 
43
- // O con Global Token (Para Large Apps)
44
- // const client = new erlc.Client({ globalToken: "..." });
47
+ if (!client.connected) {
48
+ console.error("No se pudo conectar:", client.connectionError.message);
49
+ }
45
50
  ```
46
51
 
47
52
  **TypeScript**
48
53
 
49
54
  ```typescript
50
- import { Client, getServer } from "erlc-api";
55
+ import { Client } from "erlc-api";
51
56
 
52
- const client = new Client();
57
+ const client = new Client({
58
+ serverToken: "tu-server-key-aqui",
59
+ });
60
+
61
+ await client.ready;
53
62
  ```
54
63
 
55
64
  ---
56
65
 
57
66
  ## 📖 Ejemplos de Uso
58
67
 
59
- Asegúrate de tener tu `Server Key` a mano (obtenla en los ajustes de tu servidor privado en ER:LC).
68
+ Asegúrate de tener tu `Server Key` a mano (obtenla en los ajustes de tu servidor privado en ER:LC). Cuando la key está configurada en `Client`, no necesitas volver a pasarla en cada petición.
60
69
 
61
70
  ### 🖥️ Información del Servidor
62
71
 
63
72
  ```javascript
64
- const serverToken = "tu-server-key-aqui";
65
-
66
73
  // Obtener estado del servidor
67
- const server = await erlc.getServer(serverToken);
74
+ const server = await client.getServer();
68
75
  console.log(
69
76
  `Servidor: ${server.Name} | Jugadores: ${server.CurrentPlayers}/${server.MaxPlayers}`,
70
77
  );
71
78
 
72
79
  // Obtener jugadores conectados
73
- const players = await erlc.getPlayers(serverToken);
80
+ const players = await client.getPlayers();
74
81
  console.table(players); // Muestra nombre, ID, permisos y equipo
75
82
 
76
83
  // Obtener vehículos en el mapa
77
- const vehicles = await erlc.getVehicles(serverToken);
84
+ const vehicles = await client.getVehicles();
78
85
 
79
86
  // Obtener llamadas de emergencia
80
- const emergencyCalls = await erlc.getEmergencyCalls(serverToken);
87
+ const emergencyCalls = await client.getEmergencyCalls();
81
88
 
82
89
  // Obtener información del servidor con includes de v2 en una sola petición
83
- const fullServer = await erlc.getServer(serverToken, {
90
+ const fullServer = await client.getServer({
84
91
  players: true,
85
92
  staff: true,
86
93
  emergencyCalls: true,
@@ -93,38 +100,50 @@ Accede a los historiales de actividad de tu servidor:
93
100
 
94
101
  ```javascript
95
102
  // Logs de Entradas/Salidas
96
- const joinLogs = await erlc.getJoinLogs(serverToken);
103
+ const joinLogs = await client.getJoinLogs();
97
104
 
98
105
  // Logs de Muertes (Killfeed)
99
- const killLogs = await erlc.getKillLogs(serverToken);
106
+ const killLogs = await client.getKillLogs();
100
107
 
101
108
  // Logs de Comandos ejecutados
102
- const commandLogs = await erlc.getCommandLogs(serverToken);
109
+ const commandLogs = await client.getCommandLogs();
103
110
 
104
111
  // Logs de Llamadas a Moderadores
105
- const modCalls = await erlc.getModcallLogs(serverToken);
112
+ const modCalls = await client.getModcallLogs();
106
113
  ```
107
114
 
108
115
  ### 🛠️ Gestión y Administración
109
116
 
110
117
  ```javascript
111
118
  // Ver lista de Baneos
112
- const bans = await erlc.getBans(serverToken);
119
+ const bans = await client.getBans();
113
120
 
114
121
  // Obtener Staff del servidor
115
- const staff = await erlc.getStaff(serverToken);
122
+ const staff = await client.getStaff();
123
+
124
+ // Obtener cola del servidor
125
+ const queue = await client.getQueue();
116
126
  ```
117
127
 
118
128
  ### 📢 Otros Comandos
119
129
 
120
130
  ```javascript
121
131
  // Ejecutar comando remoto (Ej: Anuncio)
122
- await erlc.runCommand(serverToken, ":h ¡Hola desde la API!");
132
+ await client.runCommand(":h ¡Hola desde la API!");
123
133
 
124
134
  // Resetear Global Key (Solo si tienes una configurada)
125
135
  // await erlc.resetGlobalKey();
126
136
  ```
127
137
 
138
+ ### Uso con Token Manual
139
+
140
+ También puedes seguir pasando la server key directamente si prefieres el estilo anterior:
141
+
142
+ ```javascript
143
+ const server = await erlc.getServer("tu-server-key-aqui");
144
+ const players = await erlc.getPlayers("tu-server-key-aqui");
145
+ ```
146
+
128
147
  ---
129
148
 
130
149
  ## 🚨 Manejo de Errores
@@ -133,7 +152,8 @@ La librería lanza errores descriptivos (`ErlcError`) que facilitan la depuraci
133
152
 
134
153
  ```javascript
135
154
  try {
136
- await erlc.getServer(serverToken);
155
+ const client = new erlc.Client({ serverToken: "token-invalido" });
156
+ await client.connect();
137
157
  } catch (error) {
138
158
  console.error(`Error ${error.code}: ${error.message}`);
139
159
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "erlc-api",
3
- "version": "3.3.2a",
3
+ "version": "3.3.3",
4
4
  "description": "An ER:LC API wrapper for JS/TS",
5
5
  "main": "index.js",
6
6
  "types": "src/types/index.d.ts",
@@ -1,9 +1,23 @@
1
1
  const erlc = require("../erlc.js");
2
- const assert = require("../functions/assert.js");
2
+ const getBans = require("../functions/server/getBans.js");
3
+ const getCommandLogs = require("../functions/server/getCommandLogs.js");
4
+ const getEmergencyCalls = require("../functions/server/getEmergencyCalls.js");
5
+ const getJoinLogs = require("../functions/server/getJoinLogs.js");
6
+ const getKillLogs = require("../functions/server/getKillLogs.js");
7
+ const getModcallLogs = require("../functions/server/getModcallLogs.js");
8
+ const getPlayers = require("../functions/server/getPlayers.js");
9
+ const getQueue = require("../functions/server/getQueue.js");
10
+ const getServer = require("../functions/server/getServer.js");
11
+ const getStaff = require("../functions/server/getStaff.js");
12
+ const getVehicles = require("../functions/server/getVehicles.js");
13
+ const runCommand = require("../functions/server/runCommand.js");
14
+ const { requestServer } = require("../functions/server/requestServer.js");
3
15
 
4
16
  /**
5
17
  * @typedef {Object} ClientConfig
6
18
  * @property {string} [globalToken] - Your ER:LC global API token
19
+ * @property {string} [serverToken] - Your ER:LC private server API token
20
+ * @property {boolean} [validateServerToken] - Validate the server token on init
7
21
  * @property {Object} [cache] - Cache configuration
8
22
  * @property {boolean} [cache.enabled] - Enable in-memory cache
9
23
  * @property {Object.<string, number>} [cache.ttlMs] - Per-endpoint TTL in ms
@@ -29,7 +43,12 @@ class Client {
29
43
  } else {
30
44
  this.options = {};
31
45
  }
46
+ this.connected = false;
47
+ this.connectionError = null;
32
48
  this.config();
49
+ this.ready = this.options.serverToken && this.options.validateServerToken !== false
50
+ ? this.connect({ throwOnError: false })
51
+ : Promise.resolve(this);
33
52
  }
34
53
 
35
54
  /**
@@ -38,13 +57,96 @@ class Client {
38
57
  */
39
58
  config() {
40
59
  // Mutate existing config object to preserve references
41
- erlc.config.globalToken = this.options.globalToken;
42
- erlc.config.serverToken = this.options.serverToken;
43
- erlc.config.cache = this.options.cache;
44
- erlc.config.logger = this.options.logger;
45
- erlc.config.fetch = this.options.fetch;
60
+ if (Object.prototype.hasOwnProperty.call(this.options, "globalToken")) {
61
+ erlc.config.globalToken = this.options.globalToken;
62
+ }
63
+ if (Object.prototype.hasOwnProperty.call(this.options, "serverToken")) {
64
+ erlc.config.serverToken = this.options.serverToken;
65
+ }
66
+ if (Object.prototype.hasOwnProperty.call(this.options, "cache")) {
67
+ erlc.config.cache = this.options.cache;
68
+ }
69
+ if (Object.prototype.hasOwnProperty.call(this.options, "logger")) {
70
+ erlc.config.logger = this.options.logger;
71
+ }
72
+ if (Object.prototype.hasOwnProperty.call(this.options, "fetch")) {
73
+ erlc.config.fetch = this.options.fetch;
74
+ }
46
75
  return erlc.config;
47
76
  }
77
+
78
+ async connect(options = {}) {
79
+ const { throwOnError = true } = options;
80
+
81
+ try {
82
+ await requestServer(this.options.serverToken, {
83
+ endpoint: "server",
84
+ useCache: false,
85
+ });
86
+
87
+ this.connected = true;
88
+ this.connectionError = null;
89
+ erlc.config.logger?.info?.("ER:LC client connected to server.");
90
+ } catch (error) {
91
+ this.connected = false;
92
+ this.connectionError = error;
93
+ erlc.config.logger?.error?.("ER:LC client failed to connect:", error);
94
+
95
+ if (throwOnError) {
96
+ throw error;
97
+ }
98
+ }
99
+
100
+ return this;
101
+ }
102
+
103
+ getServer(options = {}) {
104
+ return getServer(this.options.serverToken, options);
105
+ }
106
+
107
+ getPlayers() {
108
+ return getPlayers(this.options.serverToken);
109
+ }
110
+
111
+ getVehicles() {
112
+ return getVehicles(this.options.serverToken);
113
+ }
114
+
115
+ getEmergencyCalls() {
116
+ return getEmergencyCalls(this.options.serverToken);
117
+ }
118
+
119
+ getJoinLogs() {
120
+ return getJoinLogs(this.options.serverToken);
121
+ }
122
+
123
+ getKillLogs() {
124
+ return getKillLogs(this.options.serverToken);
125
+ }
126
+
127
+ getCommandLogs() {
128
+ return getCommandLogs(this.options.serverToken);
129
+ }
130
+
131
+ getModcallLogs() {
132
+ return getModcallLogs(this.options.serverToken);
133
+ }
134
+
135
+ getBans() {
136
+ return getBans(this.options.serverToken);
137
+ }
138
+
139
+ getStaff() {
140
+ return getStaff(this.options.serverToken);
141
+ }
142
+
143
+ getQueue() {
144
+ return getQueue(this.options.serverToken);
145
+ }
146
+
147
+ runCommand(command) {
148
+ return runCommand(this.options.serverToken, command);
149
+ }
48
150
  }
49
151
 
50
152
  module.exports = Client;
@@ -37,6 +37,11 @@ function normalizeIncludes(options = {}) {
37
37
  }
38
38
 
39
39
  module.exports = (serverToken, options = {}) => {
40
+ if (serverToken && typeof serverToken === "object") {
41
+ options = serverToken;
42
+ serverToken = undefined;
43
+ }
44
+
40
45
  const includes = normalizeIncludes(options);
41
46
 
42
47
  return requestServer(serverToken, {
@@ -8,6 +8,12 @@ function assertServerToken(serverToken) {
8
8
  }
9
9
  }
10
10
 
11
+ function resolveServerToken(serverToken, config) {
12
+ const resolvedToken = serverToken || config?.serverToken;
13
+ assertServerToken(resolvedToken);
14
+ return resolvedToken;
15
+ }
16
+
11
17
  function buildHeaders(serverToken, config, extraHeaders = {}) {
12
18
  const headers = {
13
19
  "Server-Key": serverToken,
@@ -72,21 +78,21 @@ async function requestJson(url, options) {
72
78
  }
73
79
 
74
80
  async function requestServer(serverToken, options = {}) {
75
- assertServerToken(serverToken);
76
-
77
81
  const {
78
82
  endpoint = "server",
79
83
  includes = [],
80
84
  defaultValue = {},
81
85
  transform = (data) => data,
86
+ useCache = true,
82
87
  } = options;
83
88
 
84
89
  const { fetch, config } = await getFetch();
85
- const useCache = !!config?.cache?.enabled;
90
+ const resolvedToken = resolveServerToken(serverToken, config);
91
+ const shouldCache = useCache && !!config?.cache?.enabled;
86
92
  const cacheExtras = includes.length ? includes.join(",") : "";
87
- const key = cache.makeKey(endpoint, serverToken, cacheExtras);
93
+ const key = cache.makeKey(endpoint, resolvedToken, cacheExtras);
88
94
 
89
- if (useCache) {
95
+ if (shouldCache) {
90
96
  const cached = cache.get(key);
91
97
  if (cached) {
92
98
  return cached;
@@ -96,14 +102,14 @@ async function requestServer(serverToken, options = {}) {
96
102
  const data = await requestJson(buildServerUrl(includes), {
97
103
  fetch,
98
104
  init: {
99
- headers: buildHeaders(serverToken, config),
105
+ headers: buildHeaders(resolvedToken, config),
100
106
  timeout: 10000,
101
107
  },
102
108
  });
103
109
 
104
110
  const value = (await transform(data)) ?? defaultValue;
105
111
 
106
- if (useCache) {
112
+ if (shouldCache) {
107
113
  const ttlMs = cache.getTTL(endpoint, config);
108
114
  cache.set(key, value, ttlMs);
109
115
  }
@@ -112,8 +118,6 @@ async function requestServer(serverToken, options = {}) {
112
118
  }
113
119
 
114
120
  async function requestApi(serverToken, path, options = {}) {
115
- assertServerToken(serverToken);
116
-
117
121
  const {
118
122
  baseUrl = BASEURL,
119
123
  method = "GET",
@@ -126,8 +130,9 @@ async function requestApi(serverToken, path, options = {}) {
126
130
  } = options;
127
131
 
128
132
  const { fetch, config } = await getFetch();
133
+ const resolvedToken = resolveServerToken(serverToken, config);
129
134
  const shouldCache = method === "GET" && useCache && !!config?.cache?.enabled;
130
- const key = cache.makeKey(endpoint, serverToken);
135
+ const key = cache.makeKey(endpoint, resolvedToken);
131
136
 
132
137
  if (shouldCache) {
133
138
  const cached = cache.get(key);
@@ -137,7 +142,7 @@ async function requestApi(serverToken, path, options = {}) {
137
142
  }
138
143
 
139
144
  const headers = buildHeaders(
140
- serverToken,
145
+ resolvedToken,
141
146
  config,
142
147
  body ? { "Content-Type": "application/json" } : {},
143
148
  );
@@ -171,6 +176,7 @@ async function requestLegacyServer(serverToken, path, options = {}) {
171
176
 
172
177
  module.exports = {
173
178
  assertServerToken,
179
+ resolveServerToken,
174
180
  buildHeaders,
175
181
  getFetch,
176
182
  requestServer,
@@ -1,4 +1,4 @@
1
- const { assertServerToken, requestApi } = require("./requestServer.js");
1
+ const { requestApi } = require("./requestServer.js");
2
2
 
3
3
  /**
4
4
  * Executes a command on the server.
@@ -7,7 +7,10 @@ const { assertServerToken, requestApi } = require("./requestServer.js");
7
7
  * @returns {Promise<boolean>} Promise that resolves to true if command was executed successfully
8
8
  */
9
9
  module.exports = async (serverToken, command) => {
10
- assertServerToken(serverToken);
10
+ if (command === undefined) {
11
+ command = serverToken;
12
+ serverToken = undefined;
13
+ }
11
14
 
12
15
  if (!command || typeof command !== "string") {
13
16
  throw new Error("Command is required and must be a string");
@@ -32,6 +32,8 @@ export interface ErrorInfo {
32
32
 
33
33
  export interface ClientConfig {
34
34
  globalToken?: string; // The ER:LC global API token
35
+ serverToken?: string; // The ER:LC private server API token
36
+ validateServerToken?: boolean; // Validate serverToken with /server on init
35
37
  cache?: {
36
38
  enabled?: boolean;
37
39
  ttlMs?: Record<string, number>;
@@ -166,30 +168,49 @@ export interface VSMCommandBody {
166
168
  command: string; // ":h Hey everyone!"
167
169
  }
168
170
 
169
- export function getBans(serverToken: string): Promise<ServerBan>;
170
- export function getCommandLogs(serverToken: string): Promise<CommandLog[]>;
171
- export function getJoinLogs(serverToken: string): Promise<JoinLog[]>;
172
- export function getKillLogs(serverToken: string): Promise<KillLog[]>;
173
- export function getModcallLogs(serverToken: string): Promise<ModcallLog[]>;
174
- export function getEmergencyCalls(serverToken: string): Promise<EmergencyCall[]>;
175
- export function getPlayers(serverToken: string): Promise<ServerPlayer[]>;
176
- export function getQueue(serverToken: string): Promise<number[]>;
171
+ export function getBans(serverToken?: string): Promise<ServerBan>;
172
+ export function getCommandLogs(serverToken?: string): Promise<CommandLog[]>;
173
+ export function getJoinLogs(serverToken?: string): Promise<JoinLog[]>;
174
+ export function getKillLogs(serverToken?: string): Promise<KillLog[]>;
175
+ export function getModcallLogs(serverToken?: string): Promise<ModcallLog[]>;
176
+ export function getEmergencyCalls(serverToken?: string): Promise<EmergencyCall[]>;
177
+ export function getPlayers(serverToken?: string): Promise<ServerPlayer[]>;
178
+ export function getQueue(serverToken?: string): Promise<number[]>;
177
179
  export function getServer(
178
- serverToken: string,
180
+ serverToken?: string,
179
181
  options?: ServerIncludeOptions,
180
182
  ): Promise<ServerStatus>;
181
- export function getStaff(serverToken: string): Promise<ServerStaff>;
182
- export function getVehicles(serverToken: string): Promise<VehiclesLog[]>;
183
+ export function getServer(options?: ServerIncludeOptions): Promise<ServerStatus>;
184
+ export function getStaff(serverToken?: string): Promise<ServerStaff>;
185
+ export function getVehicles(serverToken?: string): Promise<VehiclesLog[]>;
183
186
  export function runCommand(
184
187
  serverToken: string,
185
188
  command: string,
186
189
  ): Promise<boolean>;
190
+ export function runCommand(command: string): Promise<boolean>;
187
191
 
188
192
  export function resetGlobalKey(): Promise<any>;
189
193
 
190
194
  export class Client {
195
+ connected: boolean;
196
+ connectionError: Error | null;
197
+ ready: Promise<Client>;
198
+
191
199
  constructor(options?: ClientConfig);
192
200
  config(): ClientConfig;
201
+ connect(options?: { throwOnError?: boolean }): Promise<Client>;
202
+ getServer(options?: ServerIncludeOptions): Promise<ServerStatus>;
203
+ getPlayers(): Promise<ServerPlayer[]>;
204
+ getVehicles(): Promise<VehiclesLog[]>;
205
+ getEmergencyCalls(): Promise<EmergencyCall[]>;
206
+ getJoinLogs(): Promise<JoinLog[]>;
207
+ getKillLogs(): Promise<KillLog[]>;
208
+ getCommandLogs(): Promise<CommandLog[]>;
209
+ getModcallLogs(): Promise<ModcallLog[]>;
210
+ getBans(): Promise<ServerBan>;
211
+ getStaff(): Promise<ServerStaff>;
212
+ getQueue(): Promise<number[]>;
213
+ runCommand(command: string): Promise<boolean>;
193
214
  }
194
215
 
195
216
  export const utils: {
@@ -21,6 +21,8 @@ describe("Optional cache", () => {
21
21
  beforeEach(() => {
22
22
  fetchCalls = 0;
23
23
  lastUrl = "";
24
+ erlc.config.serverToken = undefined;
25
+ erlc.config.globalToken = undefined;
24
26
  erlc.config.cache.enabled = false;
25
27
  erlc.config.fetch = mockFetch;
26
28
  });
@@ -43,4 +45,57 @@ describe("Optional cache", () => {
43
45
  expect(Array.isArray(res2)).toBe(true);
44
46
  expect(fetchCalls).toBe(1);
45
47
  });
48
+
49
+ test("Client validates server token on init", async () => {
50
+ let lastHeaders = {};
51
+ const logger = {
52
+ info: jest.fn(),
53
+ error: jest.fn(),
54
+ };
55
+
56
+ erlc.config.fetch = async (url, opts) => {
57
+ fetchCalls += 1;
58
+ lastUrl = url;
59
+ lastHeaders = opts.headers;
60
+
61
+ return {
62
+ ok: true,
63
+ status: 200,
64
+ json: async () => ({ Name: "Test Server" }),
65
+ };
66
+ };
67
+
68
+ const client = new erlc.Client({
69
+ serverToken,
70
+ fetch: erlc.config.fetch,
71
+ logger,
72
+ });
73
+
74
+ expect(client.connected).toBe(false);
75
+
76
+ await client.ready;
77
+
78
+ expect(client.connected).toBe(true);
79
+ expect(client.connectionError).toBe(null);
80
+ expect(lastUrl).toBe("https://api.erlc.gg/v2/server");
81
+ expect(lastHeaders["Server-Key"]).toBe(serverToken);
82
+ expect(logger.info).toHaveBeenCalledWith("ER:LC client connected to server.");
83
+ expect(fetchCalls).toBe(1);
84
+ });
85
+
86
+ test("Client stores server token for instance methods and global fallback", async () => {
87
+ const client = new erlc.Client({
88
+ serverToken,
89
+ fetch: mockFetch,
90
+ validateServerToken: false,
91
+ });
92
+
93
+ const clientPlayers = await client.getPlayers();
94
+ const fallbackPlayers = await erlc.getPlayers();
95
+
96
+ expect(Array.isArray(clientPlayers)).toBe(true);
97
+ expect(Array.isArray(fallbackPlayers)).toBe(true);
98
+ expect(fetchCalls).toBe(2);
99
+ expect(lastUrl).toBe("https://api.erlc.gg/v2/server?Players=true");
100
+ });
46
101
  });