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.
@@ -0,0 +1,159 @@
1
+ const erlc = require("../index.js");
2
+
3
+ // Initialize the client
4
+ const client = new erlc.Client({
5
+ globalToken: "your-global-token-here",
6
+ });
7
+
8
+ client.config();
9
+
10
+ /**
11
+ * Example of comprehensive error handling with the new ERLC error system
12
+ */
13
+ async function demonstrateErrorHandling() {
14
+ const serverToken = "your-server-token-here";
15
+
16
+ try {
17
+ // This might fail with various ERLC error codes
18
+ const serverInfo = await erlc.getServer(serverToken);
19
+ console.log("✅ Server info retrieved successfully:", serverInfo.Name);
20
+ } catch (error) {
21
+ // The error is now an ErlcError instance with detailed information
22
+ console.error("❌ Error occurred:");
23
+ console.error(`Code: ${error.code}`);
24
+ console.error(`Message: ${error.message}`);
25
+ console.error(`Category: ${error.category}`);
26
+ console.error(`Severity: ${error.severity}`);
27
+
28
+ if (error.suggestions) {
29
+ console.error("💡 Suggested actions:");
30
+ error.suggestions.forEach((suggestion, index) => {
31
+ console.error(` ${index + 1}. ${suggestion}`);
32
+ });
33
+ }
34
+
35
+ if (error.retryable) {
36
+ console.error("🔄 This error might be resolved by retrying");
37
+ }
38
+
39
+ // Handle specific error codes
40
+ switch (error.code) {
41
+ case 2002:
42
+ console.error(
43
+ "🔑 Your server key is invalid or expired. Please get a new one from your server settings."
44
+ );
45
+ break;
46
+ case 4001:
47
+ console.error(
48
+ "⏱️ You're being rate limited. Waiting 60 seconds before retry..."
49
+ );
50
+ // Implement retry logic here
51
+ break;
52
+ case 3002:
53
+ console.error(
54
+ "🏃 Server is offline (no players). Waiting for players to join..."
55
+ );
56
+ break;
57
+ case 9999:
58
+ console.error(
59
+ "🔄 Server module is outdated. Please kick all players and restart the server."
60
+ );
61
+ break;
62
+ default:
63
+ console.error("🤔 Unexpected error occurred");
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Example of handling multiple API calls with proper error handling
70
+ */
71
+ async function handleMultipleApiCalls() {
72
+ const serverToken = "your-server-token-here";
73
+
74
+ const apiCalls = [
75
+ { name: "Server Info", call: () => erlc.getServer(serverToken) },
76
+ { name: "Players", call: () => erlc.getPlayers(serverToken) },
77
+ { name: "Staff", call: () => erlc.getStaff(serverToken) },
78
+ { name: "Vehicles", call: () => erlc.getVehicles(serverToken) },
79
+ ];
80
+
81
+ for (const { name, call } of apiCalls) {
82
+ try {
83
+ const result = await call();
84
+ console.log(`✅ ${name}: Success`);
85
+ } catch (error) {
86
+ console.error(`❌ ${name}: Failed`);
87
+ console.error(` Code: ${error.code}`);
88
+ console.error(` Message: ${error.message}`);
89
+
90
+ // Skip retryable errors for this example
91
+ if (!error.retryable) {
92
+ console.error(` This is a non-retryable error, stopping execution`);
93
+ break;
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Example of implementing retry logic for retryable errors
101
+ */
102
+ async function withRetry(apiCall, maxRetries = 3, delayMs = 1000) {
103
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
104
+ try {
105
+ return await apiCall();
106
+ } catch (error) {
107
+ console.error(`Attempt ${attempt} failed:`, error.message);
108
+
109
+ if (!error.retryable || attempt === maxRetries) {
110
+ throw error; // Don't retry non-retryable errors or if max retries reached
111
+ }
112
+
113
+ // Wait before retrying (exponential backoff)
114
+ const delay = delayMs * Math.pow(2, attempt - 1);
115
+ console.log(`Waiting ${delay}ms before retry...`);
116
+ await new Promise((resolve) => setTimeout(resolve, delay));
117
+ }
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Example usage of retry logic
123
+ */
124
+ async function demonstrateRetryLogic() {
125
+ const serverToken = "your-server-token-here";
126
+
127
+ try {
128
+ const players = await withRetry(() => erlc.getPlayers(serverToken));
129
+ console.log("✅ Players retrieved successfully:", players.length);
130
+ } catch (error) {
131
+ console.error("❌ Failed after all retries:", error.message);
132
+
133
+ if (error.suggestions) {
134
+ console.error("💡 Try these suggestions:");
135
+ error.suggestions.forEach((suggestion) =>
136
+ console.error(` - ${suggestion}`)
137
+ );
138
+ }
139
+ }
140
+ }
141
+
142
+ // Run examples
143
+ if (require.main === module) {
144
+ console.log("🚀 ERLC API Error Handling Examples\n");
145
+
146
+ demonstrateErrorHandling()
147
+ .then(() => console.log("\n" + "=".repeat(50) + "\n"))
148
+ .then(() => handleMultipleApiCalls())
149
+ .then(() => console.log("\n" + "=".repeat(50) + "\n"))
150
+ .then(() => demonstrateRetryLogic())
151
+ .catch(console.error);
152
+ }
153
+
154
+ module.exports = {
155
+ demonstrateErrorHandling,
156
+ handleMultipleApiCalls,
157
+ withRetry,
158
+ demonstrateRetryLogic,
159
+ };
package/package.json CHANGED
@@ -1,34 +1,36 @@
1
- {
2
- "name": "erlc-api",
3
- "version": "2.3.4",
4
- "description": "An ER:LC API wrapper for JS/TS",
5
- "main": "index.js",
6
- "types": "src/types/index.d.ts",
7
- "keywords": [
8
- "erlc",
9
- "roblox",
10
- "prc",
11
- "erlc-api",
12
- "liberty-county"
13
- ],
14
- "author": "egologics",
15
- "license": "MIT",
16
- "devDependencies": {
17
- "typescript": "^5.3.2"
18
- },
19
- "dependencies": {
20
- "erlc-api": "file:",
21
- "node-fetch": "^3.3.2"
22
- },
23
- "scripts": {
24
- "test": "echo \"Error: no test specified\" && exit 1"
25
- },
26
- "repository": {
27
- "type": "git",
28
- "url": "git+https://github.com/Exodo0/ERLC-API.git"
29
- },
30
- "bugs": {
31
- "url": "https://github.com/Exodo0/ERLC-API/issues"
32
- },
33
- "homepage": "https://github.com/Exodo0/ERLC-API#readme"
34
- }
1
+ {
2
+ "name": "erlc-api",
3
+ "version": "3.1.0",
4
+ "description": "An ER:LC API wrapper for JS/TS",
5
+ "main": "index.js",
6
+ "types": "src/types/index.d.ts",
7
+ "keywords": [
8
+ "erlc",
9
+ "roblox",
10
+ "prc",
11
+ "erlc-api",
12
+ "liberty-county"
13
+ ],
14
+ "author": "egologics",
15
+ "license": "MIT",
16
+ "devDependencies": {
17
+ "typescript": "^5.3.2"
18
+ },
19
+ "dependencies": {
20
+ "chalk": "^5.4.1",
21
+ "cli-table3": "^0.6.5",
22
+ "node-fetch": "^3.3.2",
23
+ "ora": "^8.2.0"
24
+ },
25
+ "scripts": {
26
+ "test": "echo \"Error: no test specified\" && exit 1"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/Exodo0/ERLC-API.git"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/Exodo0/ERLC-API/issues"
34
+ },
35
+ "homepage": "https://github.com/Exodo0/ERLC-API#readme"
36
+ }
@@ -1,36 +1,36 @@
1
- const erlc = require('../erlc.js')
2
- const assert = require('../functions/assert.js')
3
-
4
- /**
5
- * @typedef {Object} ClientConfig
6
- * @property {string} globalToken - Your ER:LC global API token
7
- */
8
-
9
- /**
10
- * Creates an authorised ER:LC client for requests
11
- * @class
12
- * @param {ClientConfig} options - Client Options
13
- */
14
-
15
- class Client {
16
-
17
- /**
18
- * @constructor
19
- * @param {ClientConfig} options - Client Options
20
- */
21
- constructor(options) {
22
- assert(typeof options === 'object', `Syntax error: object expected for "options", received ${typeof options}`);
23
- this.options = { ...options };
24
- }
25
-
26
- /**
27
- * Updates and returns the client configurationg
28
- * @returns {ClientConfig} The client configuration.
29
- */
30
- config() {
31
- erlc.config = this.options
32
- return erlc.config
33
- }
34
- }
35
-
1
+ const erlc = require('../erlc.js')
2
+ const assert = require('../functions/assert.js')
3
+
4
+ /**
5
+ * @typedef {Object} ClientConfig
6
+ * @property {string} globalToken - Your ER:LC global API token
7
+ */
8
+
9
+ /**
10
+ * Creates an authorised ER:LC client for requests
11
+ * @class
12
+ * @param {ClientConfig} options - Client Options
13
+ */
14
+
15
+ class Client {
16
+
17
+ /**
18
+ * @constructor
19
+ * @param {ClientConfig} options - Client Options
20
+ */
21
+ constructor(options) {
22
+ assert(typeof options === 'object', `Syntax error: object expected for "options", received ${typeof options}`);
23
+ this.options = { ...options };
24
+ }
25
+
26
+ /**
27
+ * Updates and returns the client configurationg
28
+ * @returns {ClientConfig} The client configuration.
29
+ */
30
+ config() {
31
+ erlc.config = this.options
32
+ return erlc.config
33
+ }
34
+ }
35
+
36
36
  module.exports = Client
package/src/constants.js CHANGED
@@ -1,2 +1,2 @@
1
- exports.Vanity = "https://policeroleplay.community/join?code="
1
+ exports.Vanity = "https://policeroleplay.community/join?code="
2
2
  exports.BASEURL = "https://api.policeroleplay.community/v1"
package/src/erlc.js CHANGED
@@ -1,14 +1,15 @@
1
- exports.config = {};
2
-
3
- exports.getBans = require("./functions/server/getBans.js");
4
- exports.getCommandLogs = require("./functions/server/getCommandLogs.js");
5
- exports.getJoinLogs = require("./functions/server/getJoinLogs.js");
6
- exports.getKillLogs = require("./functions/server/getKillLogs.js");
7
- exports.getModcallLogs = require("./functions/server/getModcallLogs.js");
8
- exports.getPlayers = require("./functions/server/getPlayers.js");
9
- exports.getServer = require("./functions/server/getServer.js");
10
- exports.getQueue = require("./functions/server/getQueue.js");
11
- exports.runCommand = require("./functions/server/runCommand.js");
12
- exports.getVehicles = require("./functions/server/getVehicles.js");
13
-
14
- exports.Client = require("./classes/client.js");
1
+ exports.config = {};
2
+
3
+ exports.getBans = require("./functions/server/getBans.js");
4
+ exports.getCommandLogs = require("./functions/server/getCommandLogs.js");
5
+ exports.getJoinLogs = require("./functions/server/getJoinLogs.js");
6
+ exports.getKillLogs = require("./functions/server/getKillLogs.js");
7
+ exports.getModcallLogs = require("./functions/server/getModcallLogs.js");
8
+ exports.getPlayers = require("./functions/server/getPlayers.js");
9
+ exports.getServer = require("./functions/server/getServer.js");
10
+ exports.getQueue = require("./functions/server/getQueue.js");
11
+ exports.runCommand = require("./functions/server/runCommand.js");
12
+ exports.getVehicles = require("./functions/server/getVehicles.js");
13
+ exports.getStaff = require("./functions/server/getStaff.js");
14
+
15
+ exports.Client = require("./classes/client.js");
@@ -0,0 +1,34 @@
1
+ class ErlcError extends Error {
2
+ constructor(message, code, status, originalError = null) {
3
+ super(message);
4
+ this.name = "ErlcError";
5
+ this.code = code;
6
+ this.status = status;
7
+ this.originalError = originalError;
8
+ this.timestamp = new Date().toISOString();
9
+
10
+ if (Error.captureStackTrace) {
11
+ Error.captureStackTrace(this, ErlcError);
12
+ }
13
+ }
14
+
15
+ /**
16
+ * Returns a JSON representation of the error
17
+ */
18
+ toJSON() {
19
+ return {
20
+ name: this.name,
21
+ message: this.message,
22
+ code: this.code,
23
+ status: this.status,
24
+ timestamp: this.timestamp,
25
+ stack: this.stack,
26
+ };
27
+ }
28
+
29
+ toString() {
30
+ return `${this.name} [${this.code}]: ${this.message}`;
31
+ }
32
+ }
33
+
34
+ module.exports = ErlcError;
@@ -0,0 +1,218 @@
1
+ const ERLC_ERROR_CODES = {
2
+ // System Errors (0-999)
3
+ 0: {
4
+ message: "Unknown error occurred",
5
+ description:
6
+ "An unexpected error happened. If this persists, contact PRC via an API ticket.",
7
+ category: "SYSTEM_ERROR",
8
+ severity: "HIGH",
9
+ },
10
+
11
+ // Communication Errors (1000-1999)
12
+ 1001: {
13
+ message: "Communication error with Roblox server",
14
+ description:
15
+ "Failed to communicate with Roblox or the in-game private server. The server may be experiencing issues.",
16
+ category: "COMMUNICATION_ERROR",
17
+ severity: "HIGH",
18
+ },
19
+ 1002: {
20
+ message: "Internal system error",
21
+ description: "An internal system error occurred on the ERLC API servers.",
22
+ category: "SYSTEM_ERROR",
23
+ severity: "HIGH",
24
+ },
25
+
26
+ // Authentication Errors (2000-2999)
27
+ 2000: {
28
+ message: "Missing server key",
29
+ description: "You must provide a valid server-key header in your request.",
30
+ category: "AUTHENTICATION_ERROR",
31
+ severity: "HIGH",
32
+ },
33
+ 2001: {
34
+ message: "Invalid server key format",
35
+ description: "The server-key you provided is incorrectly formatted.",
36
+ category: "AUTHENTICATION_ERROR",
37
+ severity: "HIGH",
38
+ },
39
+ 2002: {
40
+ message: "Invalid or expired server key",
41
+ description:
42
+ "The server-key you provided is invalid or has expired. Please check your server settings.",
43
+ category: "AUTHENTICATION_ERROR",
44
+ severity: "HIGH",
45
+ },
46
+ 2003: {
47
+ message: "Invalid global API key",
48
+ description:
49
+ "The global API key you provided is invalid. Please check your client configuration.",
50
+ category: "AUTHENTICATION_ERROR",
51
+ severity: "HIGH",
52
+ },
53
+ 2004: {
54
+ message: "Server key banned",
55
+ description:
56
+ "Your server-key has been banned from accessing the API. Contact PRC support for assistance.",
57
+ category: "AUTHENTICATION_ERROR",
58
+ severity: "CRITICAL",
59
+ },
60
+
61
+ // Request Errors (3000-3999)
62
+ 3001: {
63
+ message: "Invalid command provided",
64
+ description: "You must provide a valid command in the request body.",
65
+ category: "REQUEST_ERROR",
66
+ severity: "MEDIUM",
67
+ },
68
+ 3002: {
69
+ message: "Server offline",
70
+ description:
71
+ "The server you are trying to reach is currently offline (has no players).",
72
+ category: "REQUEST_ERROR",
73
+ severity: "MEDIUM",
74
+ },
75
+
76
+ // Rate Limiting & Restrictions (4000-4999)
77
+ 4001: {
78
+ message: "Rate limited",
79
+ description:
80
+ "You are being rate limited. Please reduce your request frequency and try again later.",
81
+ category: "RATE_LIMIT_ERROR",
82
+ severity: "MEDIUM",
83
+ },
84
+ 4002: {
85
+ message: "Restricted command",
86
+ description:
87
+ "The command you are attempting to run is restricted and cannot be executed.",
88
+ category: "PERMISSION_ERROR",
89
+ severity: "MEDIUM",
90
+ },
91
+ 4003: {
92
+ message: "Prohibited message",
93
+ description:
94
+ "The message you're trying to send contains prohibited content.",
95
+ category: "CONTENT_ERROR",
96
+ severity: "MEDIUM",
97
+ },
98
+
99
+ // Access Errors (9000-9999)
100
+ 9998: {
101
+ message: "Restricted resource",
102
+ description: "The resource you are trying to access is restricted.",
103
+ category: "ACCESS_ERROR",
104
+ severity: "HIGH",
105
+ },
106
+ 9999: {
107
+ message: "Outdated server module",
108
+ description:
109
+ "The module running on the in-game server is out of date. Please kick all players and try again.",
110
+ category: "VERSION_ERROR",
111
+ severity: "HIGH",
112
+ },
113
+ };
114
+
115
+ /**
116
+ * Gets error information by code
117
+ * @param {number} code - The ERLC error code
118
+ * @returns {Object} Error information object
119
+ */
120
+ function getErrorInfo(code) {
121
+ const errorInfo = ERLC_ERROR_CODES[code];
122
+ if (!errorInfo) {
123
+ return {
124
+ message: `Unknown ERLC error code: ${code}`,
125
+ description:
126
+ "This error code is not recognized. Please check the ERLC API documentation.",
127
+ category: "UNKNOWN_ERROR",
128
+ severity: "MEDIUM",
129
+ };
130
+ }
131
+ return { ...errorInfo, code };
132
+ }
133
+
134
+ /**
135
+ * Checks if an error code indicates a retryable error
136
+ * @param {number} code - The ERLC error code
137
+ * @returns {boolean} True if the error might be resolved by retrying
138
+ */
139
+ function isRetryableError(code) {
140
+ const retryableCodes = [1001, 1002, 4001]; // Communication errors and rate limits
141
+ return retryableCodes.includes(code);
142
+ }
143
+
144
+ /**
145
+ * Checks if an error code indicates an authentication issue
146
+ * @param {number} code - The ERLC error code
147
+ * @returns {boolean} True if the error is authentication-related
148
+ */
149
+ function isAuthenticationError(code) {
150
+ return code >= 2000 && code <= 2999;
151
+ }
152
+
153
+ /**
154
+ * Gets suggested actions for an error code
155
+ * @param {number} code - The ERLC error code
156
+ * @returns {string[]} Array of suggested actions
157
+ */
158
+ function getSuggestedActions(code) {
159
+ const actions = {
160
+ 0: [
161
+ "Contact PRC support via API ticket",
162
+ "Check server logs for more details",
163
+ ],
164
+ 1001: [
165
+ "Check server status",
166
+ "Verify server is online",
167
+ "Try again in a few minutes",
168
+ ],
169
+ 1002: ["Try again later", "Contact PRC support if issue persists"],
170
+ 2000: [
171
+ "Add server-key header to your request",
172
+ "Check API integration code",
173
+ ],
174
+ 2001: [
175
+ "Verify server-key format",
176
+ "Get new server-key from server settings",
177
+ ],
178
+ 2002: [
179
+ "Get new server-key from server settings",
180
+ "Verify server is still active",
181
+ ],
182
+ 2003: [
183
+ "Check global API token configuration",
184
+ "Verify client initialization",
185
+ ],
186
+ 2004: ["Contact PRC support immediately", "Review API usage policies"],
187
+ 3001: ["Check command format", "Ensure command is not empty"],
188
+ 3002: ["Wait for players to join server", "Check server status"],
189
+ 4001: [
190
+ "Reduce request frequency",
191
+ "Implement rate limiting in your code",
192
+ "Wait before retrying",
193
+ ],
194
+ 4002: ["Use a different command", "Check command permissions"],
195
+ 4003: ["Review message content", "Remove prohibited words or phrases"],
196
+ 9998: ["Check API permissions", "Contact server administrator"],
197
+ 9999: [
198
+ "Kick all players from server",
199
+ "Restart server",
200
+ "Update server module",
201
+ ],
202
+ };
203
+
204
+ return (
205
+ actions[code] || [
206
+ "Check ERLC API documentation",
207
+ "Contact PRC support if needed",
208
+ ]
209
+ );
210
+ }
211
+
212
+ module.exports = {
213
+ ERLC_ERROR_CODES,
214
+ getErrorInfo,
215
+ isRetryableError,
216
+ isAuthenticationError,
217
+ getSuggestedActions,
218
+ };
@@ -1,5 +1,5 @@
1
- module.exports = function(condition, message) {
2
- if (!condition) {
3
- throw new Error(message);
4
- }
1
+ module.exports = function(condition, message) {
2
+ if (!condition) {
3
+ throw new Error(message);
4
+ }
5
5
  }
@@ -1,28 +1,53 @@
1
- const { BASEURL } = require("../../constants.js");
2
-
3
- module.exports = (serverToken) => {
4
- return new Promise(async (resolve, reject) => {
5
- try {
6
- const fetch = await import("node-fetch");
7
- const { config } = await import("../../erlc.js");
8
-
9
- const res = await fetch.default(`${BASEURL}/server/bans`, {
10
- headers: {
11
- "Authorization": config?.globalToken,
12
- "Server-Key": serverToken,
13
- },
14
- });
15
- const data = await res.json().catch((err) => {
16
- return reject(err);
17
- });
18
-
19
- if (!res.ok) {
20
- return reject(data);
21
- }
22
-
23
- resolve(data);
24
- } catch (error) {
25
- reject(error);
26
- }
27
- });
28
- };
1
+ const { BASEURL } = require("../../constants.js");
2
+ const { processError } = require("../../utils/errorHandler.js");
3
+
4
+ /**
5
+ * Retrieves the list of banned players from a server
6
+ * @param {string} serverToken - The server API key
7
+ * @returns {Promise<Object>} Promise that resolves to banned players object
8
+ */
9
+ module.exports = (serverToken) => {
10
+ return new Promise(async (resolve, reject) => {
11
+ // Input validation
12
+ if (!serverToken || typeof serverToken !== "string") {
13
+ return reject(new Error("Server token is required and must be a string"));
14
+ }
15
+
16
+ try {
17
+ const fetch = await import("node-fetch");
18
+ const { config } = await import("../../erlc.js");
19
+
20
+ // Check if global token is configured
21
+ if (!config?.globalToken) {
22
+ const error = await processError(
23
+ new Error(
24
+ "Global token not configured. Please initialize the client first."
25
+ )
26
+ );
27
+ return reject(error);
28
+ }
29
+
30
+ const res = await fetch.default(`${BASEURL}/server/bans`, {
31
+ headers: {
32
+ Authorization: config.globalToken,
33
+ "Server-Key": serverToken,
34
+ },
35
+ timeout: 10000, // 10 second timeout
36
+ });
37
+
38
+ if (!res.ok) {
39
+ const errorData = await res
40
+ .json()
41
+ .catch(() => ({ error: "Unknown API error" }));
42
+ const error = await processError(res, errorData);
43
+ return reject(error);
44
+ }
45
+
46
+ const data = await res.json();
47
+ resolve(data || {});
48
+ } catch (error) {
49
+ const processedError = await processError(error);
50
+ reject(processedError);
51
+ }
52
+ });
53
+ };