reddb-sdk 1.0.2 → 1.0.4
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/lib/RedDBClient.js +96 -51
- package/package.json +1 -1
package/lib/RedDBClient.js
CHANGED
|
@@ -1,89 +1,134 @@
|
|
|
1
1
|
const fetch = require('node-fetch');
|
|
2
2
|
|
|
3
3
|
class RedDBClient {
|
|
4
|
-
constructor(baseURL, reddbPassword, adminPassword = null) {
|
|
4
|
+
constructor(baseURL, reddbPassword, adminPassword = null, options = {}) {
|
|
5
5
|
this.baseURL = baseURL.replace(/\/$/, '');
|
|
6
6
|
this.reddbPassword = reddbPassword;
|
|
7
7
|
this.adminPassword = adminPassword;
|
|
8
|
+
|
|
9
|
+
this.timeout = options.timeout || 5000;
|
|
10
|
+
this.retries = options.retries || 2;
|
|
11
|
+
this.debug = options.debug || false;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_log(...args) {
|
|
15
|
+
if (this.debug) console.log('[RedDB]', ...args);
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
async _safeJson(res) {
|
|
11
19
|
const text = await res.text();
|
|
20
|
+
|
|
12
21
|
try {
|
|
13
22
|
return JSON.parse(text);
|
|
14
23
|
} catch {
|
|
15
|
-
throw new Error(`Resposta inválida
|
|
24
|
+
throw new Error(`Resposta inválida do servidor:\n${text}`);
|
|
16
25
|
}
|
|
17
26
|
}
|
|
18
27
|
|
|
19
|
-
async
|
|
20
|
-
|
|
28
|
+
async _fetchWithTimeout(url, options) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const id = setTimeout(() => controller.abort(), this.timeout);
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
document,
|
|
29
|
-
reddbPassword: this.reddbPassword,
|
|
30
|
-
adminPassword: this.adminPassword
|
|
31
|
-
})
|
|
32
|
-
});
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetch(url, { ...options, signal: controller.signal });
|
|
34
|
+
clearTimeout(id);
|
|
35
|
+
return res;
|
|
36
|
+
} catch (err) {
|
|
37
|
+
clearTimeout(id);
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
if (err.name === 'AbortError') {
|
|
40
|
+
throw new Error('Timeout: cluster não respondeu a tempo');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
throw new Error('Cluster offline ou inacessível');
|
|
44
|
+
}
|
|
35
45
|
}
|
|
36
46
|
|
|
37
|
-
async
|
|
38
|
-
|
|
47
|
+
async _request(path, options = {}, isAdmin = false) {
|
|
48
|
+
let url = `${this.baseURL}${path}`;
|
|
49
|
+
let body = options.body ? JSON.parse(options.body) : {};
|
|
50
|
+
|
|
51
|
+
body.reddbPassword = this.reddbPassword;
|
|
52
|
+
|
|
53
|
+
if (isAdmin) {
|
|
54
|
+
if (!this.adminPassword) throw new Error('Admin password não fornecida');
|
|
55
|
+
body.adminPassword = this.adminPassword;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
59
|
+
|
|
60
|
+
if (options.method === 'GET') {
|
|
61
|
+
const query = new URLSearchParams(body).toString();
|
|
62
|
+
url += `?${query}`;
|
|
63
|
+
delete options.body;
|
|
64
|
+
} else {
|
|
65
|
+
options.body = JSON.stringify(body);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (let attempt = 0; attempt <= this.retries; attempt++) {
|
|
69
|
+
try {
|
|
70
|
+
this._log('Request:', options.method, url);
|
|
71
|
+
|
|
72
|
+
const res = await this._fetchWithTimeout(url, {
|
|
73
|
+
...options,
|
|
74
|
+
headers
|
|
75
|
+
});
|
|
39
76
|
|
|
40
|
-
|
|
77
|
+
const data = await this._safeJson(res);
|
|
78
|
+
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
throw new Error(data.error || `Erro HTTP ${res.status}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return data;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
this._log(`Erro (tentativa ${attempt + 1}):`, err.message);
|
|
86
|
+
|
|
87
|
+
if (attempt === this.retries) {
|
|
88
|
+
throw new Error(`Falha após ${this.retries + 1} tentativas: ${err.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async set(key, value, document = 'users.json') {
|
|
95
|
+
return this._request('/set', {
|
|
41
96
|
method: 'POST',
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
document,
|
|
46
|
-
reddbPassword: this.reddbPassword,
|
|
47
|
-
adminPassword: this.adminPassword
|
|
48
|
-
})
|
|
49
|
-
});
|
|
97
|
+
body: JSON.stringify({ key, value, document })
|
|
98
|
+
}, true);
|
|
99
|
+
}
|
|
50
100
|
|
|
51
|
-
|
|
101
|
+
async delete(key, document = 'users.json') {
|
|
102
|
+
return this._request('/delete', {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
body: JSON.stringify({ key, document })
|
|
105
|
+
}, true);
|
|
52
106
|
}
|
|
53
107
|
|
|
54
108
|
async get(key, document = 'users.json') {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
109
|
+
return this._request(`/get/${encodeURIComponent(key)}`, {
|
|
110
|
+
method: 'GET',
|
|
111
|
+
body: JSON.stringify({ document })
|
|
112
|
+
});
|
|
58
113
|
}
|
|
59
114
|
|
|
60
115
|
async listKeys(document = 'users.json') {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
116
|
+
return this._request('/listKeys', {
|
|
117
|
+
method: 'GET',
|
|
118
|
+
body: JSON.stringify({ document })
|
|
119
|
+
});
|
|
64
120
|
}
|
|
65
121
|
|
|
66
122
|
async reset() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
method: 'POST',
|
|
71
|
-
headers: { 'Content-Type': 'application/json' },
|
|
72
|
-
body: JSON.stringify({
|
|
73
|
-
reddbPassword: this.reddbPassword,
|
|
74
|
-
adminPassword: this.adminPassword
|
|
75
|
-
})
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
return this._safeJson(res);
|
|
123
|
+
return this._request('/admin/reset', {
|
|
124
|
+
method: 'POST'
|
|
125
|
+
}, true);
|
|
79
126
|
}
|
|
80
127
|
|
|
81
128
|
async listAdminKeys() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const res = await fetch(url);
|
|
86
|
-
return this._safeJson(res);
|
|
129
|
+
return this._request('/admin/keys', {
|
|
130
|
+
method: 'POST'
|
|
131
|
+
}, true);
|
|
87
132
|
}
|
|
88
133
|
}
|
|
89
134
|
|