erlc-api 2.3.4 → 3.1.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/.gitattributes +2 -2
- package/README.md +497 -110
- package/examples/error-handling.js +159 -0
- package/package.json +36 -34
- package/src/classes/client.js +35 -35
- package/src/constants.js +1 -1
- package/src/erlc.js +15 -14
- package/src/errors/ErlcError.js +34 -0
- package/src/errors/errorCodes.js +218 -0
- package/src/functions/assert.js +4 -4
- package/src/functions/server/getBans.js +53 -28
- package/src/functions/server/getCommandLogs.js +53 -28
- package/src/functions/server/getJoinLogs.js +53 -28
- package/src/functions/server/getKillLogs.js +53 -28
- package/src/functions/server/getModcallLogs.js +53 -28
- package/src/functions/server/getPlayers.js +53 -28
- package/src/functions/server/getQueue.js +53 -28
- package/src/functions/server/getServer.js +105 -52
- package/src/functions/server/getStaff.js +53 -0
- package/src/functions/server/getVehicles.js +53 -28
- package/src/functions/server/runCommand.js +67 -29
- package/src/types/custom.d.ts +4 -4
- package/src/types/index.d.ts +127 -91
- package/src/utils/errorHandler.js +158 -0
package/.gitattributes
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
# Auto detect text files and perform LF normalization
|
|
2
|
-
* text=auto
|
|
1
|
+
# Auto detect text files and perform LF normalization
|
|
2
|
+
* text=auto
|
package/README.md
CHANGED
|
@@ -1,110 +1,497 @@
|
|
|
1
|
-
# ER:LC API Wrapper
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
1
|
+
# 🚔 ER:LC API Wrapper
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/erlc-api)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
A comprehensive, lightweight, and fully-typed API wrapper for Emergency Response: Liberty County (ER:LC) with 100% API coverage, robust error handling, and TypeScript support.
|
|
7
|
+
|
|
8
|
+
## ✨ Features
|
|
9
|
+
|
|
10
|
+
- 🎯 **100% API Coverage** - All ER:LC API endpoints supported
|
|
11
|
+
- 🛡️ **Robust Error Handling** - Comprehensive error catching and meaningful error messages
|
|
12
|
+
- 📝 **Full TypeScript Support** - Complete type definitions for all methods and responses
|
|
13
|
+
- ⚡ **Optimized Performance** - Efficient request handling with timeout management
|
|
14
|
+
- 🔒 **Secure** - Built-in validation and secure token handling
|
|
15
|
+
- 📚 **Well Documented** - Extensive documentation and examples
|
|
16
|
+
- 🚀 **Easy to Use** - Simple, intuitive API design
|
|
17
|
+
|
|
18
|
+
## 📦 Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install erlc-api
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bun add erlc-api
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 🚀 Quick Start
|
|
29
|
+
|
|
30
|
+
### Basic Setup
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
const erlc = require("erlc-api");
|
|
34
|
+
|
|
35
|
+
// Initialize the client with your global token
|
|
36
|
+
const client = new erlc.Client({
|
|
37
|
+
globalToken: "your-global-token-here", // Get this from ER:LC developers
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Register your client
|
|
41
|
+
client.config();
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### TypeScript Setup
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import erlc from "erlc-api";
|
|
48
|
+
|
|
49
|
+
const client = new erlc.Client({
|
|
50
|
+
globalToken: "your-global-token-here",
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
client.config();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 📖 API Methods
|
|
57
|
+
|
|
58
|
+
### 🖥️ Server Information
|
|
59
|
+
|
|
60
|
+
#### Get Server Details
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const getServerInfo = async () => {
|
|
64
|
+
try {
|
|
65
|
+
const serverToken = "your-server-api-key"; // From Server Settings
|
|
66
|
+
const server = await erlc.getServer(serverToken);
|
|
67
|
+
|
|
68
|
+
console.log(server);
|
|
69
|
+
/*
|
|
70
|
+
Expected Response:
|
|
71
|
+
{
|
|
72
|
+
Name: "Your Server Name",
|
|
73
|
+
OwnerUsername: "ServerOwner",
|
|
74
|
+
CoOwnerUsernames: ["CoOwner1", "CoOwner2"],
|
|
75
|
+
CurrentPlayers: 25,
|
|
76
|
+
MaxPlayers: 40,
|
|
77
|
+
JoinKey: "ABC123",
|
|
78
|
+
AccVerifiedReq: "Disabled", // "Email" | "Phone/ID"
|
|
79
|
+
TeamBalance: true,
|
|
80
|
+
VanityURL: "https://policeroleplay.community/join?code=ABC123"
|
|
81
|
+
}
|
|
82
|
+
*/
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error("Error fetching server info:", error.message);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### Get Current Players
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const getCurrentPlayers = async () => {
|
|
93
|
+
try {
|
|
94
|
+
const players = await erlc.getPlayers(serverToken);
|
|
95
|
+
|
|
96
|
+
console.log(players);
|
|
97
|
+
/*
|
|
98
|
+
Expected Response:
|
|
99
|
+
[
|
|
100
|
+
{
|
|
101
|
+
Player: "PlayerName:123456789",
|
|
102
|
+
Permission: "Server Owner", // "Member" | "Moderator" | "Server Administrator"
|
|
103
|
+
Team: "Police" // "Civilian" | "Fire" | "Sheriff"
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
*/
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error("Error fetching players:", error.message);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Get Server Queue
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
const getServerQueue = async () => {
|
|
117
|
+
try {
|
|
118
|
+
const queue = await erlc.getQueue(serverToken);
|
|
119
|
+
console.log(`Players in queue: ${queue.length}`);
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error("Error fetching queue:", error.message);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 👥 Staff Management
|
|
127
|
+
|
|
128
|
+
#### Get Staff Information
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
const getStaffInfo = async () => {
|
|
132
|
+
try {
|
|
133
|
+
const staff = await erlc.getStaff(serverToken);
|
|
134
|
+
|
|
135
|
+
console.log(staff);
|
|
136
|
+
/*
|
|
137
|
+
Expected Response:
|
|
138
|
+
{
|
|
139
|
+
CoOwners: [123456789, 987654321],
|
|
140
|
+
Admins: { "123456789": "AdminName" },
|
|
141
|
+
Mods: { "987654321": "ModName" }
|
|
142
|
+
}
|
|
143
|
+
*/
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error("Error fetching staff:", error.message);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 📊 Server Logs
|
|
151
|
+
|
|
152
|
+
#### Get Join/Leave Logs
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const getJoinLogs = async () => {
|
|
156
|
+
try {
|
|
157
|
+
const logs = await erlc.getJoinLogs(serverToken);
|
|
158
|
+
|
|
159
|
+
logs.forEach((log) => {
|
|
160
|
+
const action = log.Join ? "joined" : "left";
|
|
161
|
+
console.log(
|
|
162
|
+
`${log.Player} ${action} at ${new Date(log.Timestamp * 1000)}`
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error("Error fetching join logs:", error.message);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Get Kill Logs
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const getKillLogs = async () => {
|
|
175
|
+
try {
|
|
176
|
+
const kills = await erlc.getKillLogs(serverToken);
|
|
177
|
+
|
|
178
|
+
kills.forEach((kill) => {
|
|
179
|
+
console.log(
|
|
180
|
+
`${kill.Killer} killed ${kill.Killed} at ${new Date(
|
|
181
|
+
kill.Timestamp * 1000
|
|
182
|
+
)}`
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.error("Error fetching kill logs:", error.message);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Get Command Logs
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const getCommandLogs = async () => {
|
|
195
|
+
try {
|
|
196
|
+
const commands = await erlc.getCommandLogs(serverToken);
|
|
197
|
+
|
|
198
|
+
commands.forEach((cmd) => {
|
|
199
|
+
console.log(`${cmd.Player} executed: ${cmd.Command}`);
|
|
200
|
+
});
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error("Error fetching command logs:", error.message);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### Get Moderator Call Logs
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
const getModCalls = async () => {
|
|
211
|
+
try {
|
|
212
|
+
const modcalls = await erlc.getModcallLogs(serverToken);
|
|
213
|
+
|
|
214
|
+
modcalls.forEach((call) => {
|
|
215
|
+
const status = call.Moderator
|
|
216
|
+
? `answered by ${call.Moderator}`
|
|
217
|
+
: "unanswered";
|
|
218
|
+
console.log(`${call.Caller} made a modcall - ${status}`);
|
|
219
|
+
});
|
|
220
|
+
} catch (error) {
|
|
221
|
+
console.error("Error fetching modcall logs:", error.message);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 🚗 Vehicle Management
|
|
227
|
+
|
|
228
|
+
#### Get Server Vehicles
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
const getVehicles = async () => {
|
|
232
|
+
try {
|
|
233
|
+
const vehicles = await erlc.getVehicles(serverToken);
|
|
234
|
+
|
|
235
|
+
vehicles.forEach((vehicle) => {
|
|
236
|
+
console.log(
|
|
237
|
+
`${vehicle.Name} owned by ${vehicle.Owner} - Texture: ${
|
|
238
|
+
vehicle.Texture || "Default"
|
|
239
|
+
}`
|
|
240
|
+
);
|
|
241
|
+
});
|
|
242
|
+
} catch (error) {
|
|
243
|
+
console.error("Error fetching vehicles:", error.message);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 🔨 Server Management
|
|
249
|
+
|
|
250
|
+
#### Execute Server Commands
|
|
251
|
+
|
|
252
|
+
```javascript
|
|
253
|
+
const executeCommand = async () => {
|
|
254
|
+
try {
|
|
255
|
+
const success = await erlc.runCommand(
|
|
256
|
+
serverToken,
|
|
257
|
+
":h Welcome to our server!"
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
if (success) {
|
|
261
|
+
console.log("Command executed successfully!");
|
|
262
|
+
}
|
|
263
|
+
} catch (error) {
|
|
264
|
+
console.error("Error executing command:", error.message);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Get Server Bans
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
const getBannedPlayers = async () => {
|
|
273
|
+
try {
|
|
274
|
+
const bans = await erlc.getBans(serverToken);
|
|
275
|
+
|
|
276
|
+
Object.entries(bans).forEach(([playerId, playerName]) => {
|
|
277
|
+
console.log(`${playerName} (${playerId}) is banned`);
|
|
278
|
+
});
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error("Error fetching bans:", error.message);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## 🛠️ Advanced Usage
|
|
286
|
+
|
|
287
|
+
### Error Handling Best Practices
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
const handleApiCall = async () => {
|
|
291
|
+
try {
|
|
292
|
+
const result = await erlc.getServer(serverToken);
|
|
293
|
+
return result;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
// The error is now an ErlcError with detailed information
|
|
296
|
+
console.error(`Error ${error.code}: ${error.message}`);
|
|
297
|
+
console.error(`Category: ${error.category}, Severity: ${error.severity}`);
|
|
298
|
+
|
|
299
|
+
// Handle specific ERLC error codes
|
|
300
|
+
switch (error.code) {
|
|
301
|
+
case 2002:
|
|
302
|
+
console.error(
|
|
303
|
+
"Invalid server key - get a new one from server settings"
|
|
304
|
+
);
|
|
305
|
+
break;
|
|
306
|
+
case 4001:
|
|
307
|
+
console.error("Rate limited - reduce request frequency");
|
|
308
|
+
break;
|
|
309
|
+
case 3002:
|
|
310
|
+
console.error("Server offline - wait for players to join");
|
|
311
|
+
break;
|
|
312
|
+
case 9999:
|
|
313
|
+
console.error("Server module outdated - restart server");
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Show suggested actions
|
|
318
|
+
if (error.suggestions) {
|
|
319
|
+
console.error("Suggested actions:");
|
|
320
|
+
error.suggestions.forEach((action) => console.error(`- ${action}`));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check if error is retryable
|
|
324
|
+
if (error.retryable) {
|
|
325
|
+
console.error("This error might be resolved by retrying");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
throw error; // Re-throw if needed
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Batch Operations
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
const getServerOverview = async (serverToken) => {
|
|
337
|
+
try {
|
|
338
|
+
// Execute multiple API calls concurrently
|
|
339
|
+
const [serverInfo, players, staff, vehicles] = await Promise.all([
|
|
340
|
+
erlc.getServer(serverToken),
|
|
341
|
+
erlc.getPlayers(serverToken),
|
|
342
|
+
erlc.getStaff(serverToken),
|
|
343
|
+
erlc.getVehicles(serverToken),
|
|
344
|
+
]);
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
server: serverInfo,
|
|
348
|
+
playerCount: players.length,
|
|
349
|
+
staffCount:
|
|
350
|
+
Object.keys(staff.Admins).length + Object.keys(staff.Mods).length,
|
|
351
|
+
vehicleCount: vehicles.length,
|
|
352
|
+
};
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error("Error getting server overview:", error.message);
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## 🔑 Authentication
|
|
361
|
+
|
|
362
|
+
### Getting Your Tokens
|
|
363
|
+
|
|
364
|
+
1. **Global Token**: Contact ER:LC developers through their [Discord](https://discord.gg/prc) to request increased API limits
|
|
365
|
+
2. **Server Token**: Found in your server settings within ER:LC
|
|
366
|
+
|
|
367
|
+
### Token Security
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
// ❌ Don't hardcode tokens
|
|
371
|
+
const client = new erlc.Client({
|
|
372
|
+
globalToken: "your-token-here",
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// ✅ Use environment variables
|
|
376
|
+
const client = new erlc.Client({
|
|
377
|
+
globalToken: process.env.ERLC_GLOBAL_TOKEN,
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## 📝 TypeScript Support
|
|
382
|
+
|
|
383
|
+
The package includes comprehensive TypeScript definitions:
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
import erlc, { ServerStatus, ServerPlayer, JoinLog } from "erlc-api";
|
|
387
|
+
|
|
388
|
+
const client = new erlc.Client({
|
|
389
|
+
globalToken: process.env.ERLC_GLOBAL_TOKEN!,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
client.config();
|
|
393
|
+
|
|
394
|
+
// Fully typed responses
|
|
395
|
+
const server: ServerStatus = await erlc.getServer(serverToken);
|
|
396
|
+
const players: ServerPlayer[] = await erlc.getPlayers(serverToken);
|
|
397
|
+
const joinLogs: JoinLog[] = await erlc.getJoinLogs(serverToken);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## ⚡ Performance Tips
|
|
401
|
+
|
|
402
|
+
1. **Use Promise.all()** for concurrent requests when fetching multiple endpoints
|
|
403
|
+
2. **Implement caching** for frequently accessed data that doesn't change often
|
|
404
|
+
3. **Handle rate limits** by implementing retry logic with exponential backoff
|
|
405
|
+
4. **Use timeouts** - all methods have built-in 10-15 second timeouts
|
|
406
|
+
|
|
407
|
+
## 🐛 Error Types
|
|
408
|
+
|
|
409
|
+
The wrapper provides comprehensive error handling with specific ERLC error codes:
|
|
410
|
+
|
|
411
|
+
### ERLC Error Codes
|
|
412
|
+
|
|
413
|
+
| Code | Category | Description |
|
|
414
|
+
| ---- | -------------------- | -------------------------------------- |
|
|
415
|
+
| 0 | System Error | Unknown error occurred |
|
|
416
|
+
| 1001 | Communication Error | Error communicating with Roblox server |
|
|
417
|
+
| 1002 | System Error | Internal system error |
|
|
418
|
+
| 2000 | Authentication Error | Missing server key |
|
|
419
|
+
| 2001 | Authentication Error | Invalid server key format |
|
|
420
|
+
| 2002 | Authentication Error | Invalid or expired server key |
|
|
421
|
+
| 2003 | Authentication Error | Invalid global API key |
|
|
422
|
+
| 2004 | Authentication Error | Server key banned |
|
|
423
|
+
| 3001 | Request Error | Invalid command provided |
|
|
424
|
+
| 3002 | Request Error | Server offline (no players) |
|
|
425
|
+
| 4001 | Rate Limit Error | Rate limited |
|
|
426
|
+
| 4002 | Permission Error | Restricted command |
|
|
427
|
+
| 4003 | Content Error | Prohibited message |
|
|
428
|
+
| 9998 | Access Error | Restricted resource |
|
|
429
|
+
| 9999 | Version Error | Outdated server module |
|
|
430
|
+
|
|
431
|
+
### Error Properties
|
|
432
|
+
|
|
433
|
+
All errors are instances of `ErlcError` with these properties:
|
|
434
|
+
|
|
435
|
+
- `code`: ERLC error code or HTTP status
|
|
436
|
+
- `message`: Human-readable error message
|
|
437
|
+
- `category`: Error category (e.g., "AUTHENTICATION_ERROR")
|
|
438
|
+
- `severity`: Error severity ("LOW", "MEDIUM", "HIGH", "CRITICAL")
|
|
439
|
+
- `suggestions`: Array of suggested actions to resolve the error
|
|
440
|
+
- `retryable`: Boolean indicating if the error might be resolved by retrying
|
|
441
|
+
- `timestamp`: ISO timestamp when the error occurred
|
|
442
|
+
|
|
443
|
+
### Retry Logic Example
|
|
444
|
+
|
|
445
|
+
```javascript
|
|
446
|
+
async function withRetry(apiCall, maxRetries = 3) {
|
|
447
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
448
|
+
try {
|
|
449
|
+
return await apiCall();
|
|
450
|
+
} catch (error) {
|
|
451
|
+
if (!error.retryable || attempt === maxRetries) {
|
|
452
|
+
throw error;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Wait before retrying with exponential backoff
|
|
456
|
+
const delay = 1000 * Math.pow(2, attempt - 1);
|
|
457
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Usage
|
|
463
|
+
const players = await withRetry(() => erlc.getPlayers(serverToken));
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
## 🤝 Contributing
|
|
467
|
+
|
|
468
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
469
|
+
|
|
470
|
+
## 📄 License
|
|
471
|
+
|
|
472
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
473
|
+
|
|
474
|
+
## 🔗 Links
|
|
475
|
+
|
|
476
|
+
- **Discord Bot**: [Invite to your server](https://discord.com/oauth2/authorize?client_id=1014990793280323624)
|
|
477
|
+
- **API Documentation**: [PRC API Docs](https://apidocs.policeroleplay.community/reference/api-reference)
|
|
478
|
+
- **Discord Support**: [Join PRC Discord](https://discord.gg/prc)
|
|
479
|
+
- **Custom Liveries**: [Browse Collection](https://github.com/Exodo0/ERLC-API/tree/main/Custom%20Liveries)
|
|
480
|
+
|
|
481
|
+
## 👨💻 Credits
|
|
482
|
+
|
|
483
|
+
- **Library Development**: [Egologics](https://twitter.com/0Adexus0)
|
|
484
|
+
- **NPM Package**: [ERLC-API](https://www.npmjs.com/package/erlc-api)
|
|
485
|
+
- **API Development**: [Police Roleplay Community](https://twitter.com/PRC_Roblox)
|
|
486
|
+
- **Community Support**: [PRC Discord Community](https://discord.gg/prc)
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
<div align="center">
|
|
491
|
+
<p>Made with ❤️ for the ER:LC community</p>
|
|
492
|
+
<p>
|
|
493
|
+
<a href="https://github.com/Exodo0/ERLC-API">⭐ Star us on GitHub</a> •
|
|
494
|
+
<a href="https://discord.gg/prc">💬 Join our Discord</a> •
|
|
495
|
+
<a href="https://twitter.com/0Adexus0">🐦 Follow on Twitter</a>
|
|
496
|
+
</p>
|
|
497
|
+
</div>
|