unb-api 1.5.1 → 2.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.
package/README.md CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  `npm install unb-api`
12
12
 
13
+ Requires Node.js 18 or newer (uses the built-in `fetch`). For older Node.js versions, use `unb-api@1`.
14
+
13
15
  ## Documentation
14
16
 
15
17
  Full API documentation is located at [https://unbelievaboat.com/api/docs](https://unbelievaboat.com/api/docs)
package/eslintrc.js CHANGED
@@ -1,5 +1,12 @@
1
1
  module.exports = {
2
2
  'extends': 'eslint:recommended',
3
+ 'env': {
4
+ 'node': true,
5
+ 'es2020': true
6
+ },
7
+ 'globals': {
8
+ 'fetch': 'readonly'
9
+ },
3
10
  'rules': {
4
11
  'indent': ['error', 4],
5
12
  'linebreak-style': ['error', 'unix'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unb-api",
3
- "version": "1.5.1",
3
+ "version": "2.0.0",
4
4
  "description": "API wrapper for UnbelievaBoat Discord Bot API",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -16,12 +16,12 @@
16
16
  ],
17
17
  "author": "unbelievable",
18
18
  "license": "MIT",
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
19
22
  "devDependencies": {
20
23
  "@types/node": "^10.0.7",
21
24
  "eslint": "^6.7.2",
22
25
  "typescript": "^2.6.2"
23
- },
24
- "dependencies": {
25
- "axios": "^1.20.0"
26
26
  }
27
27
  }
@@ -1,4 +1,3 @@
1
- const axios = require('axios');
2
1
  const Bucket = require('./util/Bucket');
3
2
  const { APIError, HTTPError } = require('./errors');
4
3
  const MajorParams = ['guilds'];
@@ -7,13 +6,6 @@ class RequestHandler {
7
6
  constructor(client) {
8
7
  this._client = client;
9
8
  this.ratelimits = {};
10
- this.axiosInstance = axios.create({
11
- baseURL: this._client.baseURL,
12
- headers: {
13
- 'Authorization': this._client.token,
14
- 'Content-Type': 'application/json'
15
- }
16
- });
17
9
  }
18
10
 
19
11
  async request(method, endpoint, data = {}, params = {}, _attempts = 0) {
@@ -32,7 +24,7 @@ class RequestHandler {
32
24
  };
33
25
 
34
26
  try {
35
- const { data: responseData, status, headers } = await this.axiosInstance(options);
27
+ const { data: responseData, status, statusText, headers } = await this.fetch(options);
36
28
 
37
29
  // Increase the number of attempts
38
30
  ++_attempts;
@@ -44,21 +36,17 @@ class RequestHandler {
44
36
  resolve(responseData);
45
37
  } else if (status === 429) {
46
38
  if (_attempts >= this._client.maxRetries) {
47
- this.rejectWithError(options, responseData, status, reject);
39
+ this.rejectWithError(options, responseData, status, statusText, reject);
48
40
  } else {
49
41
  this.retryRequest(method, endpoint, data, params, _attempts, headers, resolve, reject);
50
42
  }
51
43
  } else {
52
- this.rejectWithError(options, responseData, status, reject);
44
+ this.rejectWithError(options, responseData, status, statusText, reject);
53
45
  }
54
46
 
55
47
  callback();
56
48
  } catch (error) {
57
- if (axios.isAxiosError(error)) {
58
- this.rejectWithError(options, error.response.data, error.response.status, reject);
59
- } else {
60
- reject(error);
61
- }
49
+ reject(error);
62
50
  callback();
63
51
  }
64
52
  };
@@ -67,11 +55,49 @@ class RequestHandler {
67
55
  });
68
56
  }
69
57
 
70
- rejectWithError(options, data, status, reject) {
58
+ async fetch(options) {
59
+ const url = new URL(`${this._client.baseURL.replace(/\/+$/, '')}${options.url}`);
60
+ for (const [key, value] of Object.entries(options.params || {})) {
61
+ if (value === undefined || value === null) continue;
62
+ if (Array.isArray(value)) {
63
+ for (const v of value) url.searchParams.append(`${key}[]`, v);
64
+ } else {
65
+ url.searchParams.append(key, value);
66
+ }
67
+ }
68
+
69
+ const response = await fetch(url, {
70
+ method: options.method,
71
+ headers: {
72
+ 'Authorization': this._client.token,
73
+ 'Content-Type': 'application/json'
74
+ },
75
+ body: ['GET', 'HEAD'].includes(options.method) ? undefined : JSON.stringify(options.data)
76
+ });
77
+
78
+ const text = await response.text();
79
+ let data = text;
80
+ if (text) {
81
+ try {
82
+ data = JSON.parse(text);
83
+ } catch (e) {
84
+ // Not JSON (e.g. an HTML error page from a proxy), keep the raw text
85
+ }
86
+ }
87
+
88
+ return {
89
+ data,
90
+ status: response.status,
91
+ statusText: response.statusText,
92
+ headers: Object.fromEntries(response.headers)
93
+ };
94
+ }
95
+
96
+ rejectWithError(options, data, status, statusText, reject) {
71
97
  if (data && data.message) {
72
- reject(new APIError(options, { data, status }));
98
+ reject(new APIError(options, { data, status, statusText }));
73
99
  } else {
74
- reject(new HTTPError(options, { data, status }));
100
+ reject(new HTTPError(options, { data, status, statusText }));
75
101
  }
76
102
  }
77
103