vigor-fetch 1.0.7 → 1.0.9
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 +4 -12
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +188 -283
- package/dist/index.mjs +187 -264
- package/package.json +11 -9
- package/dist/index.d.mts +0 -76
package/README.md
CHANGED
|
@@ -58,9 +58,7 @@ npm install vigor-fetch
|
|
|
58
58
|
|
|
59
59
|
```javascript
|
|
60
60
|
|
|
61
|
-
import
|
|
62
|
-
|
|
63
|
-
const vigor = new Vigor();
|
|
61
|
+
import vigor from 'vigor-fetch';
|
|
64
62
|
|
|
65
63
|
const data = await vigor.fetch("https://api.example.com")
|
|
66
64
|
.path("/v1/users")
|
|
@@ -80,9 +78,7 @@ const data = await vigor.fetch("https://api.example.com")
|
|
|
80
78
|
|
|
81
79
|
```javascript
|
|
82
80
|
|
|
83
|
-
import
|
|
84
|
-
|
|
85
|
-
const vigor = new Vigor();
|
|
81
|
+
import vigor from 'vigor-fetch';
|
|
86
82
|
|
|
87
83
|
const apiClient = vigor.fetch("https://api.myapp.com")
|
|
88
84
|
.headers({ "Content-Type": "application/json" })
|
|
@@ -98,9 +94,7 @@ const settings = await apiClient.path("/settings").request();
|
|
|
98
94
|
|
|
99
95
|
```javascript
|
|
100
96
|
|
|
101
|
-
import
|
|
102
|
-
|
|
103
|
-
const vigor = new Vigor();
|
|
97
|
+
import vigor from 'vigor-fetch';
|
|
104
98
|
|
|
105
99
|
const tasks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(id => () =>
|
|
106
100
|
vigor.fetch("https://api.com").path(`/data/${id}`).request()
|
|
@@ -118,9 +112,7 @@ const results = await vigor.all()
|
|
|
118
112
|
|
|
119
113
|
```javascript
|
|
120
114
|
|
|
121
|
-
import
|
|
122
|
-
|
|
123
|
-
const vigor = new Vigor();
|
|
115
|
+
import vigor from 'vigor-fetch';
|
|
124
116
|
|
|
125
117
|
const api = vigor.fetch("https://api.com")
|
|
126
118
|
.beforeRequest((opt) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,290 +1,195 @@
|
|
|
1
|
-
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
-
var __export = (target, all) => {
|
|
6
|
-
for (var name in all)
|
|
7
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
16
|
-
};
|
|
17
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
'use strict';
|
|
18
2
|
|
|
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
|
-
_next(changes) {
|
|
67
|
-
return new _VigorFetch(this._origin, { ...this._config, ...changes });
|
|
68
|
-
}
|
|
69
|
-
path(arg) {
|
|
70
|
-
return this._next({ path: arg });
|
|
71
|
-
}
|
|
72
|
-
method(arg) {
|
|
73
|
-
return this._next({ method: arg });
|
|
74
|
-
}
|
|
75
|
-
offset(arg) {
|
|
76
|
-
return this._next({ offset: arg });
|
|
77
|
-
}
|
|
78
|
-
headers(arg) {
|
|
79
|
-
return this._next({ headers: arg });
|
|
80
|
-
}
|
|
81
|
-
body(arg) {
|
|
82
|
-
return this._next({ body: arg });
|
|
83
|
-
}
|
|
84
|
-
count(arg) {
|
|
85
|
-
return this._next({ count: arg });
|
|
86
|
-
}
|
|
87
|
-
max(arg) {
|
|
88
|
-
return this._next({ max: arg });
|
|
89
|
-
}
|
|
90
|
-
wait(arg) {
|
|
91
|
-
return this._next({ wait: arg });
|
|
92
|
-
}
|
|
93
|
-
backoff(arg) {
|
|
94
|
-
return this._next({ backoff: arg });
|
|
95
|
-
}
|
|
96
|
-
unretry(arg) {
|
|
97
|
-
return this._next({ unretry: new Set(arg) });
|
|
98
|
-
}
|
|
99
|
-
retryHeader(...arg) {
|
|
100
|
-
return this._next({ retryHeader: [...this._config.retryHeader, ...arg] });
|
|
101
|
-
}
|
|
102
|
-
original(arg) {
|
|
103
|
-
return this._next({ original: arg });
|
|
104
|
-
}
|
|
105
|
-
parse(arg) {
|
|
106
|
-
return this._next({ parse: arg });
|
|
107
|
-
}
|
|
108
|
-
query(arg) {
|
|
109
|
-
return this._next({ query: { ...this._config.query, ...arg } });
|
|
110
|
-
}
|
|
111
|
-
jitter(arg) {
|
|
112
|
-
return this._next({ jitter: arg });
|
|
113
|
-
}
|
|
114
|
-
beforeRequest(...arg) {
|
|
115
|
-
return this._next({ beforeRequest: [...this._config.beforeRequest, ...arg] });
|
|
116
|
-
}
|
|
117
|
-
afterRequest(...arg) {
|
|
118
|
-
return this._next({ afterRequest: [...this._config.afterRequest, ...arg] });
|
|
119
|
-
}
|
|
120
|
-
beforeResponse(...arg) {
|
|
121
|
-
return this._next({ beforeResponse: [...this._config.beforeResponse, ...arg] });
|
|
122
|
-
}
|
|
123
|
-
afterResponse(...arg) {
|
|
124
|
-
return this._next({ afterResponse: [...this._config.afterResponse, ...arg] });
|
|
125
|
-
}
|
|
126
|
-
onError(...arg) {
|
|
127
|
-
return this._next({ onError: [...this._config.onError, ...arg] });
|
|
128
|
-
}
|
|
129
|
-
async request() {
|
|
130
|
-
const {
|
|
131
|
-
path,
|
|
132
|
-
method,
|
|
133
|
-
offset,
|
|
134
|
-
headers,
|
|
135
|
-
body,
|
|
136
|
-
query,
|
|
137
|
-
count,
|
|
138
|
-
max,
|
|
139
|
-
wait,
|
|
140
|
-
backoff,
|
|
141
|
-
unretry,
|
|
142
|
-
jitter,
|
|
143
|
-
original,
|
|
144
|
-
parse,
|
|
145
|
-
retryHeader,
|
|
146
|
-
beforeRequest,
|
|
147
|
-
afterRequest,
|
|
148
|
-
beforeResponse,
|
|
149
|
-
afterResponse,
|
|
150
|
-
onError
|
|
151
|
-
} = this._config;
|
|
152
|
-
try {
|
|
153
|
-
if (!/^(https?|data|blob|file|about):\/\//.test(this._origin)) {
|
|
154
|
-
throw new VigorError(`[vigor] ${this._origin} >> Invalid Protocol`, {
|
|
155
|
-
url: this._origin,
|
|
156
|
-
status: 0,
|
|
157
|
-
message: "Invalid Protocol"
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
const urlObj = new URL(path.replace(/^\//, ""), this._origin + "/");
|
|
161
|
-
Object.entries(query).forEach(([key, value]) => {
|
|
162
|
-
if (value !== null && value !== void 0) urlObj.searchParams.append(key, String(value));
|
|
163
|
-
});
|
|
164
|
-
const url = urlObj.href;
|
|
165
|
-
const isJson = Array.isArray(body) || !!body && Object.getPrototypeOf(body) === Object.prototype;
|
|
166
|
-
const waitTimeout = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
167
|
-
let option = {
|
|
168
|
-
...offset,
|
|
169
|
-
method: method || (body ? "POST" : "GET"),
|
|
170
|
-
headers: { ...isJson && { "Content-Type": "application/json" }, ...headers },
|
|
171
|
-
...body && { body: isJson ? JSON.stringify(body) : body }
|
|
172
|
-
};
|
|
173
|
-
for (const hook of beforeRequest) {
|
|
174
|
-
const modified = await hook(option);
|
|
175
|
-
if (modified) option = { ...option, ...modified };
|
|
176
|
-
}
|
|
177
|
-
let req;
|
|
178
|
-
for (let i = 0; i < count; i++) {
|
|
179
|
-
const controller = new AbortController();
|
|
180
|
-
const abort = setTimeout(() => controller.abort(), max);
|
|
181
|
-
option.signal = controller.signal;
|
|
3
|
+
class VigorError extends Error {
|
|
4
|
+
constructor(text, { url = null, status = 0, message, data = null }) {
|
|
5
|
+
super(text);
|
|
6
|
+
this.name = "VigorError";
|
|
7
|
+
this.url = url;
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.message = message || text;
|
|
10
|
+
this.data = data;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
class VigorFetch {
|
|
14
|
+
constructor(origin, config) {
|
|
15
|
+
this._origin = origin;
|
|
16
|
+
this._config = config || {
|
|
17
|
+
path: "", method: null, offset: {}, headers: {}, body: null,
|
|
18
|
+
count: 5, max: 5000, wait: 10000, backoff: 1.3,
|
|
19
|
+
unretry: new Set([400, 401, 403, 404, 405, 413, 422]),
|
|
20
|
+
retryHeader: ["retry-after", "ratelimit-reset", "x-ratelimit-reset", "x-retry-after", "x-amz-retry-after", "chrome-proxy-next-link"],
|
|
21
|
+
original: false, parse: null, query: {}, jitter: 500,
|
|
22
|
+
beforeRequest: [], afterRequest: [], beforeResponse: [], afterResponse: [], onError: []
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
_next(changes) {
|
|
26
|
+
return new VigorFetch(this._origin, { ...this._config, ...changes });
|
|
27
|
+
}
|
|
28
|
+
path(arg) { return this._next({ path: arg }); }
|
|
29
|
+
method(arg) { return this._next({ method: arg }); }
|
|
30
|
+
offset(arg) { return this._next({ offset: arg }); }
|
|
31
|
+
headers(arg) { return this._next({ headers: arg }); }
|
|
32
|
+
body(arg) { return this._next({ body: arg }); }
|
|
33
|
+
count(arg) { return this._next({ count: arg }); }
|
|
34
|
+
max(arg) { return this._next({ max: arg }); }
|
|
35
|
+
wait(arg) { return this._next({ wait: arg }); }
|
|
36
|
+
backoff(arg) { return this._next({ backoff: arg }); }
|
|
37
|
+
unretry(arg) { return this._next({ unretry: new Set(arg) }); }
|
|
38
|
+
retryHeader(...arg) { return this._next({ retryHeader: [...this._config.retryHeader, ...arg] }); }
|
|
39
|
+
original(arg) { return this._next({ original: arg }); }
|
|
40
|
+
parse(arg) { return this._next({ parse: arg }); }
|
|
41
|
+
query(arg) { return this._next({ query: { ...this._config.query, ...arg } }); }
|
|
42
|
+
jitter(arg) { return this._next({ jitter: arg }); }
|
|
43
|
+
beforeRequest(...arg) { return this._next({ beforeRequest: [...this._config.beforeRequest, ...arg] }); }
|
|
44
|
+
afterRequest(...arg) { return this._next({ afterRequest: [...this._config.afterRequest, ...arg] }); }
|
|
45
|
+
beforeResponse(...arg) { return this._next({ beforeResponse: [...this._config.beforeResponse, ...arg] }); }
|
|
46
|
+
afterResponse(...arg) { return this._next({ afterResponse: [...this._config.afterResponse, ...arg] }); }
|
|
47
|
+
onError(...arg) { return this._next({ onError: [...this._config.onError, ...arg] }); }
|
|
48
|
+
async request() {
|
|
49
|
+
const { path, method, offset, headers, body, query, count, max, wait, backoff, unretry, jitter, original, parse, retryHeader, beforeRequest, afterRequest, beforeResponse, afterResponse, onError, } = this._config;
|
|
182
50
|
try {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
51
|
+
if (!/^(https?|data|blob|file|about):\/\//.test(this._origin)) {
|
|
52
|
+
throw new VigorError(`[vigor] ${this._origin} >> Invalid Protocol`, {
|
|
53
|
+
url: this._origin, status: 0, message: "Invalid Protocol"
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
const urlObj = new URL(path.replace(/^\//, ""), this._origin + "/");
|
|
57
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
58
|
+
if (value !== null && value !== undefined)
|
|
59
|
+
urlObj.searchParams.append(key, String(value));
|
|
60
|
+
});
|
|
61
|
+
const url = urlObj.href;
|
|
62
|
+
const isJson = Array.isArray(body) || (!!body && Object.getPrototypeOf(body) === Object.prototype);
|
|
63
|
+
const waitTimeout = (time) => new Promise(resolve => setTimeout(resolve, time));
|
|
64
|
+
let option = {
|
|
65
|
+
...offset,
|
|
66
|
+
method: method || (body ? "POST" : "GET"),
|
|
67
|
+
headers: { ...(isJson && { "Content-Type": "application/json" }), ...headers },
|
|
68
|
+
...(body && { body: isJson ? JSON.stringify(body) : body }),
|
|
69
|
+
};
|
|
70
|
+
for (const hook of beforeRequest) {
|
|
71
|
+
const modified = await hook(option);
|
|
72
|
+
if (modified)
|
|
73
|
+
option = { ...option, ...modified };
|
|
74
|
+
}
|
|
75
|
+
let req;
|
|
76
|
+
for (let i = 0; i < count; i++) {
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
const abort = setTimeout(() => controller.abort(), max);
|
|
79
|
+
option.signal = controller.signal;
|
|
80
|
+
try {
|
|
81
|
+
req = await fetch(url, option);
|
|
82
|
+
for (const hook of afterRequest) {
|
|
83
|
+
req = (await hook(req)) || req;
|
|
84
|
+
}
|
|
85
|
+
if (req.ok) {
|
|
86
|
+
clearTimeout(abort);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
clearTimeout(abort);
|
|
92
|
+
if (i === count - 1)
|
|
93
|
+
throw new VigorError(`[vigor] ${url} >> Network Error`, { url, status: 0, message: "Network Error" });
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
clearTimeout(abort);
|
|
97
|
+
}
|
|
98
|
+
if (req) {
|
|
99
|
+
const status = req.status;
|
|
100
|
+
if (unretry.has(status))
|
|
101
|
+
throw new VigorError(`[vigor] ${url} >> Unretry ${status}`, { url, status, message: "Unretry", data: status });
|
|
102
|
+
const basic = Math.min(Math.pow(backoff, i) * 1000, wait) + Math.random() * jitter;
|
|
103
|
+
if (status === 429) {
|
|
104
|
+
const rHeader = retryHeader.map(h => req?.headers.get(h)).find(Boolean);
|
|
105
|
+
const delay = rHeader ? (isNaN(Number(rHeader)) ? new Date(rHeader).getTime() - Date.now() : Number(rHeader) * 1000) : 0;
|
|
106
|
+
const parsedDelay = Math.max(0, delay) + Math.random() * jitter;
|
|
107
|
+
if (parsedDelay > wait)
|
|
108
|
+
throw new VigorError(`[vigor] ${url} >> Timeouted ${parsedDelay}ms`, { url, status, message: "Timeouted", data: parsedDelay });
|
|
109
|
+
await waitTimeout(parsedDelay || basic);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
await waitTimeout(basic);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!req)
|
|
117
|
+
throw new Error("No response");
|
|
118
|
+
let currentReq = req;
|
|
119
|
+
for (const hook of beforeResponse) {
|
|
120
|
+
currentReq = await hook(currentReq);
|
|
121
|
+
}
|
|
122
|
+
if (!currentReq.ok)
|
|
123
|
+
throw new VigorError(`[vigor] ${url} >> Failed`, { url, status: currentReq.status, message: "Failed" });
|
|
124
|
+
let res = await (async () => {
|
|
125
|
+
if (original)
|
|
126
|
+
return currentReq;
|
|
127
|
+
if (parse) {
|
|
128
|
+
const target = currentReq[parse];
|
|
129
|
+
return typeof target === 'function' ? await target.call(currentReq) : target;
|
|
130
|
+
}
|
|
131
|
+
const contentType = currentReq.headers.get("Content-Type") || "";
|
|
132
|
+
if (/json/.test(contentType))
|
|
133
|
+
return await currentReq.json();
|
|
134
|
+
if (/(image|video|audio|pdf)/.test(contentType))
|
|
135
|
+
return await currentReq.blob();
|
|
136
|
+
return await currentReq.text();
|
|
137
|
+
})();
|
|
138
|
+
for (const hook of afterResponse) {
|
|
139
|
+
res = await hook(res);
|
|
140
|
+
}
|
|
141
|
+
return res;
|
|
196
142
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
await waitTimeout(parsedDelay || basic);
|
|
207
|
-
} else {
|
|
208
|
-
await waitTimeout(basic);
|
|
209
|
-
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
let currentError = error;
|
|
145
|
+
for (const hook of onError) {
|
|
146
|
+
const result = await hook(currentError);
|
|
147
|
+
if (result !== undefined && !(result instanceof Error))
|
|
148
|
+
return result;
|
|
149
|
+
currentError = result || currentError;
|
|
150
|
+
}
|
|
151
|
+
throw currentError;
|
|
210
152
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
class VigorAll {
|
|
156
|
+
constructor(config) {
|
|
157
|
+
this._config = config || { limit: 10, jitter: 1000, promises: [] };
|
|
158
|
+
}
|
|
159
|
+
_next(changes) { return new VigorAll({ ...this._config, ...changes }); }
|
|
160
|
+
limit(arg) { return this._next({ limit: arg }); }
|
|
161
|
+
jitter(arg) { return this._next({ jitter: arg }); }
|
|
162
|
+
promises(...args) { return this._next({ promises: [...this._config.promises, ...args] }); }
|
|
163
|
+
async request() {
|
|
164
|
+
const { limit, jitter, promises } = this._config;
|
|
165
|
+
const results = [];
|
|
166
|
+
const executing = new Set();
|
|
167
|
+
for (const task of promises) {
|
|
168
|
+
const p = Promise.resolve()
|
|
169
|
+
.then(() => new Promise(res => setTimeout(res, Math.random() * jitter)))
|
|
170
|
+
.then(() => task());
|
|
171
|
+
results.push(p);
|
|
172
|
+
executing.add(p);
|
|
173
|
+
p.finally(() => executing.delete(p));
|
|
174
|
+
if (executing.size >= limit)
|
|
175
|
+
await Promise.race(executing);
|
|
223
176
|
}
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
res = await hook(res);
|
|
231
|
-
}
|
|
232
|
-
return res;
|
|
233
|
-
} catch (error) {
|
|
234
|
-
let currentError = error;
|
|
235
|
-
for (const hook of onError) {
|
|
236
|
-
const result = await hook(currentError);
|
|
237
|
-
if (result !== void 0 && !(result instanceof Error)) return result;
|
|
238
|
-
currentError = result || currentError;
|
|
239
|
-
}
|
|
240
|
-
throw currentError;
|
|
177
|
+
const ready = await Promise.allSettled(results);
|
|
178
|
+
return ready.map(i => {
|
|
179
|
+
if (i.status === "fulfilled")
|
|
180
|
+
return i.value;
|
|
181
|
+
return i.reason instanceof VigorError ? i.reason : new VigorError(i.reason?.message || "Unknown", { message: i.reason?.message || "Unknown" });
|
|
182
|
+
});
|
|
241
183
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
constructor(config) {
|
|
247
|
-
this._config = config || { limit: 10, jitter: 1e3, promises: [] };
|
|
248
|
-
}
|
|
249
|
-
_next(changes) {
|
|
250
|
-
return new _VigorAll({ ...this._config, ...changes });
|
|
251
|
-
}
|
|
252
|
-
limit(arg) {
|
|
253
|
-
return this._next({ limit: arg });
|
|
254
|
-
}
|
|
255
|
-
jitter(arg) {
|
|
256
|
-
return this._next({ jitter: arg });
|
|
257
|
-
}
|
|
258
|
-
promises(...args) {
|
|
259
|
-
return this._next({ promises: [...this._config.promises, ...args] });
|
|
260
|
-
}
|
|
261
|
-
async request() {
|
|
262
|
-
const { limit, jitter, promises } = this._config;
|
|
263
|
-
const results = [];
|
|
264
|
-
const executing = /* @__PURE__ */ new Set();
|
|
265
|
-
for (const task of promises) {
|
|
266
|
-
const p = Promise.resolve().then(() => new Promise((res) => setTimeout(res, Math.random() * jitter))).then(() => task());
|
|
267
|
-
results.push(p);
|
|
268
|
-
executing.add(p);
|
|
269
|
-
p.finally(() => executing.delete(p));
|
|
270
|
-
if (executing.size >= limit) await Promise.race(executing);
|
|
184
|
+
}
|
|
185
|
+
class Vigor {
|
|
186
|
+
fetch(origin, config) {
|
|
187
|
+
return new VigorFetch(origin, config);
|
|
271
188
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
};
|
|
280
|
-
var Vigor = class {
|
|
281
|
-
fetch(origin, config) {
|
|
282
|
-
return new VigorFetch(origin, config);
|
|
283
|
-
}
|
|
284
|
-
all(config) {
|
|
285
|
-
return new VigorAll(config);
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
var vigor = new Vigor();
|
|
289
|
-
var index_default = vigor;
|
|
290
|
-
if (module.exports.default) module.exports = module.exports.default;
|
|
189
|
+
all(config) {
|
|
190
|
+
return new VigorAll(config);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const vigor = new Vigor();
|
|
194
|
+
|
|
195
|
+
module.exports = vigor;
|
package/dist/index.mjs
CHANGED
|
@@ -1,270 +1,193 @@
|
|
|
1
|
-
|
|
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
|
-
return
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
method(arg) {
|
|
50
|
-
return this._next({ method: arg });
|
|
51
|
-
}
|
|
52
|
-
offset(arg) {
|
|
53
|
-
return this._next({ offset: arg });
|
|
54
|
-
}
|
|
55
|
-
headers(arg) {
|
|
56
|
-
return this._next({ headers: arg });
|
|
57
|
-
}
|
|
58
|
-
body(arg) {
|
|
59
|
-
return this._next({ body: arg });
|
|
60
|
-
}
|
|
61
|
-
count(arg) {
|
|
62
|
-
return this._next({ count: arg });
|
|
63
|
-
}
|
|
64
|
-
max(arg) {
|
|
65
|
-
return this._next({ max: arg });
|
|
66
|
-
}
|
|
67
|
-
wait(arg) {
|
|
68
|
-
return this._next({ wait: arg });
|
|
69
|
-
}
|
|
70
|
-
backoff(arg) {
|
|
71
|
-
return this._next({ backoff: arg });
|
|
72
|
-
}
|
|
73
|
-
unretry(arg) {
|
|
74
|
-
return this._next({ unretry: new Set(arg) });
|
|
75
|
-
}
|
|
76
|
-
retryHeader(...arg) {
|
|
77
|
-
return this._next({ retryHeader: [...this._config.retryHeader, ...arg] });
|
|
78
|
-
}
|
|
79
|
-
original(arg) {
|
|
80
|
-
return this._next({ original: arg });
|
|
81
|
-
}
|
|
82
|
-
parse(arg) {
|
|
83
|
-
return this._next({ parse: arg });
|
|
84
|
-
}
|
|
85
|
-
query(arg) {
|
|
86
|
-
return this._next({ query: { ...this._config.query, ...arg } });
|
|
87
|
-
}
|
|
88
|
-
jitter(arg) {
|
|
89
|
-
return this._next({ jitter: arg });
|
|
90
|
-
}
|
|
91
|
-
beforeRequest(...arg) {
|
|
92
|
-
return this._next({ beforeRequest: [...this._config.beforeRequest, ...arg] });
|
|
93
|
-
}
|
|
94
|
-
afterRequest(...arg) {
|
|
95
|
-
return this._next({ afterRequest: [...this._config.afterRequest, ...arg] });
|
|
96
|
-
}
|
|
97
|
-
beforeResponse(...arg) {
|
|
98
|
-
return this._next({ beforeResponse: [...this._config.beforeResponse, ...arg] });
|
|
99
|
-
}
|
|
100
|
-
afterResponse(...arg) {
|
|
101
|
-
return this._next({ afterResponse: [...this._config.afterResponse, ...arg] });
|
|
102
|
-
}
|
|
103
|
-
onError(...arg) {
|
|
104
|
-
return this._next({ onError: [...this._config.onError, ...arg] });
|
|
105
|
-
}
|
|
106
|
-
async request() {
|
|
107
|
-
const {
|
|
108
|
-
path,
|
|
109
|
-
method,
|
|
110
|
-
offset,
|
|
111
|
-
headers,
|
|
112
|
-
body,
|
|
113
|
-
query,
|
|
114
|
-
count,
|
|
115
|
-
max,
|
|
116
|
-
wait,
|
|
117
|
-
backoff,
|
|
118
|
-
unretry,
|
|
119
|
-
jitter,
|
|
120
|
-
original,
|
|
121
|
-
parse,
|
|
122
|
-
retryHeader,
|
|
123
|
-
beforeRequest,
|
|
124
|
-
afterRequest,
|
|
125
|
-
beforeResponse,
|
|
126
|
-
afterResponse,
|
|
127
|
-
onError
|
|
128
|
-
} = this._config;
|
|
129
|
-
try {
|
|
130
|
-
if (!/^(https?|data|blob|file|about):\/\//.test(this._origin)) {
|
|
131
|
-
throw new VigorError(`[vigor] ${this._origin} >> Invalid Protocol`, {
|
|
132
|
-
url: this._origin,
|
|
133
|
-
status: 0,
|
|
134
|
-
message: "Invalid Protocol"
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
const urlObj = new URL(path.replace(/^\//, ""), this._origin + "/");
|
|
138
|
-
Object.entries(query).forEach(([key, value]) => {
|
|
139
|
-
if (value !== null && value !== void 0) urlObj.searchParams.append(key, String(value));
|
|
140
|
-
});
|
|
141
|
-
const url = urlObj.href;
|
|
142
|
-
const isJson = Array.isArray(body) || !!body && Object.getPrototypeOf(body) === Object.prototype;
|
|
143
|
-
const waitTimeout = (time) => new Promise((resolve) => setTimeout(resolve, time));
|
|
144
|
-
let option = {
|
|
145
|
-
...offset,
|
|
146
|
-
method: method || (body ? "POST" : "GET"),
|
|
147
|
-
headers: { ...isJson && { "Content-Type": "application/json" }, ...headers },
|
|
148
|
-
...body && { body: isJson ? JSON.stringify(body) : body }
|
|
149
|
-
};
|
|
150
|
-
for (const hook of beforeRequest) {
|
|
151
|
-
const modified = await hook(option);
|
|
152
|
-
if (modified) option = { ...option, ...modified };
|
|
153
|
-
}
|
|
154
|
-
let req;
|
|
155
|
-
for (let i = 0; i < count; i++) {
|
|
156
|
-
const controller = new AbortController();
|
|
157
|
-
const abort = setTimeout(() => controller.abort(), max);
|
|
158
|
-
option.signal = controller.signal;
|
|
1
|
+
class VigorError extends Error {
|
|
2
|
+
constructor(text, { url = null, status = 0, message, data = null }) {
|
|
3
|
+
super(text);
|
|
4
|
+
this.name = "VigorError";
|
|
5
|
+
this.url = url;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.message = message || text;
|
|
8
|
+
this.data = data;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
class VigorFetch {
|
|
12
|
+
constructor(origin, config) {
|
|
13
|
+
this._origin = origin;
|
|
14
|
+
this._config = config || {
|
|
15
|
+
path: "", method: null, offset: {}, headers: {}, body: null,
|
|
16
|
+
count: 5, max: 5000, wait: 10000, backoff: 1.3,
|
|
17
|
+
unretry: new Set([400, 401, 403, 404, 405, 413, 422]),
|
|
18
|
+
retryHeader: ["retry-after", "ratelimit-reset", "x-ratelimit-reset", "x-retry-after", "x-amz-retry-after", "chrome-proxy-next-link"],
|
|
19
|
+
original: false, parse: null, query: {}, jitter: 500,
|
|
20
|
+
beforeRequest: [], afterRequest: [], beforeResponse: [], afterResponse: [], onError: []
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
_next(changes) {
|
|
24
|
+
return new VigorFetch(this._origin, { ...this._config, ...changes });
|
|
25
|
+
}
|
|
26
|
+
path(arg) { return this._next({ path: arg }); }
|
|
27
|
+
method(arg) { return this._next({ method: arg }); }
|
|
28
|
+
offset(arg) { return this._next({ offset: arg }); }
|
|
29
|
+
headers(arg) { return this._next({ headers: arg }); }
|
|
30
|
+
body(arg) { return this._next({ body: arg }); }
|
|
31
|
+
count(arg) { return this._next({ count: arg }); }
|
|
32
|
+
max(arg) { return this._next({ max: arg }); }
|
|
33
|
+
wait(arg) { return this._next({ wait: arg }); }
|
|
34
|
+
backoff(arg) { return this._next({ backoff: arg }); }
|
|
35
|
+
unretry(arg) { return this._next({ unretry: new Set(arg) }); }
|
|
36
|
+
retryHeader(...arg) { return this._next({ retryHeader: [...this._config.retryHeader, ...arg] }); }
|
|
37
|
+
original(arg) { return this._next({ original: arg }); }
|
|
38
|
+
parse(arg) { return this._next({ parse: arg }); }
|
|
39
|
+
query(arg) { return this._next({ query: { ...this._config.query, ...arg } }); }
|
|
40
|
+
jitter(arg) { return this._next({ jitter: arg }); }
|
|
41
|
+
beforeRequest(...arg) { return this._next({ beforeRequest: [...this._config.beforeRequest, ...arg] }); }
|
|
42
|
+
afterRequest(...arg) { return this._next({ afterRequest: [...this._config.afterRequest, ...arg] }); }
|
|
43
|
+
beforeResponse(...arg) { return this._next({ beforeResponse: [...this._config.beforeResponse, ...arg] }); }
|
|
44
|
+
afterResponse(...arg) { return this._next({ afterResponse: [...this._config.afterResponse, ...arg] }); }
|
|
45
|
+
onError(...arg) { return this._next({ onError: [...this._config.onError, ...arg] }); }
|
|
46
|
+
async request() {
|
|
47
|
+
const { path, method, offset, headers, body, query, count, max, wait, backoff, unretry, jitter, original, parse, retryHeader, beforeRequest, afterRequest, beforeResponse, afterResponse, onError, } = this._config;
|
|
159
48
|
try {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
49
|
+
if (!/^(https?|data|blob|file|about):\/\//.test(this._origin)) {
|
|
50
|
+
throw new VigorError(`[vigor] ${this._origin} >> Invalid Protocol`, {
|
|
51
|
+
url: this._origin, status: 0, message: "Invalid Protocol"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const urlObj = new URL(path.replace(/^\//, ""), this._origin + "/");
|
|
55
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
56
|
+
if (value !== null && value !== undefined)
|
|
57
|
+
urlObj.searchParams.append(key, String(value));
|
|
58
|
+
});
|
|
59
|
+
const url = urlObj.href;
|
|
60
|
+
const isJson = Array.isArray(body) || (!!body && Object.getPrototypeOf(body) === Object.prototype);
|
|
61
|
+
const waitTimeout = (time) => new Promise(resolve => setTimeout(resolve, time));
|
|
62
|
+
let option = {
|
|
63
|
+
...offset,
|
|
64
|
+
method: method || (body ? "POST" : "GET"),
|
|
65
|
+
headers: { ...(isJson && { "Content-Type": "application/json" }), ...headers },
|
|
66
|
+
...(body && { body: isJson ? JSON.stringify(body) : body }),
|
|
67
|
+
};
|
|
68
|
+
for (const hook of beforeRequest) {
|
|
69
|
+
const modified = await hook(option);
|
|
70
|
+
if (modified)
|
|
71
|
+
option = { ...option, ...modified };
|
|
72
|
+
}
|
|
73
|
+
let req;
|
|
74
|
+
for (let i = 0; i < count; i++) {
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const abort = setTimeout(() => controller.abort(), max);
|
|
77
|
+
option.signal = controller.signal;
|
|
78
|
+
try {
|
|
79
|
+
req = await fetch(url, option);
|
|
80
|
+
for (const hook of afterRequest) {
|
|
81
|
+
req = (await hook(req)) || req;
|
|
82
|
+
}
|
|
83
|
+
if (req.ok) {
|
|
84
|
+
clearTimeout(abort);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
clearTimeout(abort);
|
|
90
|
+
if (i === count - 1)
|
|
91
|
+
throw new VigorError(`[vigor] ${url} >> Network Error`, { url, status: 0, message: "Network Error" });
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
clearTimeout(abort);
|
|
95
|
+
}
|
|
96
|
+
if (req) {
|
|
97
|
+
const status = req.status;
|
|
98
|
+
if (unretry.has(status))
|
|
99
|
+
throw new VigorError(`[vigor] ${url} >> Unretry ${status}`, { url, status, message: "Unretry", data: status });
|
|
100
|
+
const basic = Math.min(Math.pow(backoff, i) * 1000, wait) + Math.random() * jitter;
|
|
101
|
+
if (status === 429) {
|
|
102
|
+
const rHeader = retryHeader.map(h => req?.headers.get(h)).find(Boolean);
|
|
103
|
+
const delay = rHeader ? (isNaN(Number(rHeader)) ? new Date(rHeader).getTime() - Date.now() : Number(rHeader) * 1000) : 0;
|
|
104
|
+
const parsedDelay = Math.max(0, delay) + Math.random() * jitter;
|
|
105
|
+
if (parsedDelay > wait)
|
|
106
|
+
throw new VigorError(`[vigor] ${url} >> Timeouted ${parsedDelay}ms`, { url, status, message: "Timeouted", data: parsedDelay });
|
|
107
|
+
await waitTimeout(parsedDelay || basic);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
await waitTimeout(basic);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!req)
|
|
115
|
+
throw new Error("No response");
|
|
116
|
+
let currentReq = req;
|
|
117
|
+
for (const hook of beforeResponse) {
|
|
118
|
+
currentReq = await hook(currentReq);
|
|
119
|
+
}
|
|
120
|
+
if (!currentReq.ok)
|
|
121
|
+
throw new VigorError(`[vigor] ${url} >> Failed`, { url, status: currentReq.status, message: "Failed" });
|
|
122
|
+
let res = await (async () => {
|
|
123
|
+
if (original)
|
|
124
|
+
return currentReq;
|
|
125
|
+
if (parse) {
|
|
126
|
+
const target = currentReq[parse];
|
|
127
|
+
return typeof target === 'function' ? await target.call(currentReq) : target;
|
|
128
|
+
}
|
|
129
|
+
const contentType = currentReq.headers.get("Content-Type") || "";
|
|
130
|
+
if (/json/.test(contentType))
|
|
131
|
+
return await currentReq.json();
|
|
132
|
+
if (/(image|video|audio|pdf)/.test(contentType))
|
|
133
|
+
return await currentReq.blob();
|
|
134
|
+
return await currentReq.text();
|
|
135
|
+
})();
|
|
136
|
+
for (const hook of afterResponse) {
|
|
137
|
+
res = await hook(res);
|
|
138
|
+
}
|
|
139
|
+
return res;
|
|
173
140
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
await waitTimeout(parsedDelay || basic);
|
|
184
|
-
} else {
|
|
185
|
-
await waitTimeout(basic);
|
|
186
|
-
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
let currentError = error;
|
|
143
|
+
for (const hook of onError) {
|
|
144
|
+
const result = await hook(currentError);
|
|
145
|
+
if (result !== undefined && !(result instanceof Error))
|
|
146
|
+
return result;
|
|
147
|
+
currentError = result || currentError;
|
|
148
|
+
}
|
|
149
|
+
throw currentError;
|
|
187
150
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
class VigorAll {
|
|
154
|
+
constructor(config) {
|
|
155
|
+
this._config = config || { limit: 10, jitter: 1000, promises: [] };
|
|
156
|
+
}
|
|
157
|
+
_next(changes) { return new VigorAll({ ...this._config, ...changes }); }
|
|
158
|
+
limit(arg) { return this._next({ limit: arg }); }
|
|
159
|
+
jitter(arg) { return this._next({ jitter: arg }); }
|
|
160
|
+
promises(...args) { return this._next({ promises: [...this._config.promises, ...args] }); }
|
|
161
|
+
async request() {
|
|
162
|
+
const { limit, jitter, promises } = this._config;
|
|
163
|
+
const results = [];
|
|
164
|
+
const executing = new Set();
|
|
165
|
+
for (const task of promises) {
|
|
166
|
+
const p = Promise.resolve()
|
|
167
|
+
.then(() => new Promise(res => setTimeout(res, Math.random() * jitter)))
|
|
168
|
+
.then(() => task());
|
|
169
|
+
results.push(p);
|
|
170
|
+
executing.add(p);
|
|
171
|
+
p.finally(() => executing.delete(p));
|
|
172
|
+
if (executing.size >= limit)
|
|
173
|
+
await Promise.race(executing);
|
|
200
174
|
}
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
for (const hook of onError) {
|
|
213
|
-
const result = await hook(currentError);
|
|
214
|
-
if (result !== void 0 && !(result instanceof Error)) return result;
|
|
215
|
-
currentError = result || currentError;
|
|
216
|
-
}
|
|
217
|
-
throw currentError;
|
|
175
|
+
const ready = await Promise.allSettled(results);
|
|
176
|
+
return ready.map(i => {
|
|
177
|
+
if (i.status === "fulfilled")
|
|
178
|
+
return i.value;
|
|
179
|
+
return i.reason instanceof VigorError ? i.reason : new VigorError(i.reason?.message || "Unknown", { message: i.reason?.message || "Unknown" });
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
class Vigor {
|
|
184
|
+
fetch(origin, config) {
|
|
185
|
+
return new VigorFetch(origin, config);
|
|
218
186
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
var VigorAll = class _VigorAll {
|
|
222
|
-
_config;
|
|
223
|
-
constructor(config) {
|
|
224
|
-
this._config = config || { limit: 10, jitter: 1e3, promises: [] };
|
|
225
|
-
}
|
|
226
|
-
_next(changes) {
|
|
227
|
-
return new _VigorAll({ ...this._config, ...changes });
|
|
228
|
-
}
|
|
229
|
-
limit(arg) {
|
|
230
|
-
return this._next({ limit: arg });
|
|
231
|
-
}
|
|
232
|
-
jitter(arg) {
|
|
233
|
-
return this._next({ jitter: arg });
|
|
234
|
-
}
|
|
235
|
-
promises(...args) {
|
|
236
|
-
return this._next({ promises: [...this._config.promises, ...args] });
|
|
237
|
-
}
|
|
238
|
-
async request() {
|
|
239
|
-
const { limit, jitter, promises } = this._config;
|
|
240
|
-
const results = [];
|
|
241
|
-
const executing = /* @__PURE__ */ new Set();
|
|
242
|
-
for (const task of promises) {
|
|
243
|
-
const p = Promise.resolve().then(() => new Promise((res) => setTimeout(res, Math.random() * jitter))).then(() => task());
|
|
244
|
-
results.push(p);
|
|
245
|
-
executing.add(p);
|
|
246
|
-
p.finally(() => executing.delete(p));
|
|
247
|
-
if (executing.size >= limit) await Promise.race(executing);
|
|
187
|
+
all(config) {
|
|
188
|
+
return new VigorAll(config);
|
|
248
189
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return i.reason instanceof VigorError ? i.reason : new VigorError(((_a = i.reason) == null ? void 0 : _a.message) || "Unknown", { message: ((_b = i.reason) == null ? void 0 : _b.message) || "Unknown" });
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
var Vigor = class {
|
|
258
|
-
fetch(origin, config) {
|
|
259
|
-
return new VigorFetch(origin, config);
|
|
260
|
-
}
|
|
261
|
-
all(config) {
|
|
262
|
-
return new VigorAll(config);
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
var vigor = new Vigor();
|
|
266
|
-
var index_default = vigor;
|
|
267
|
-
export {
|
|
268
|
-
index_default as default
|
|
269
|
-
};
|
|
270
|
-
if (module.exports.default) module.exports = module.exports.default;
|
|
190
|
+
}
|
|
191
|
+
const vigor = new Vigor();
|
|
192
|
+
|
|
193
|
+
export { vigor as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigor-fetch",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Smart, zero-dependency HTTP client with self-healing retries for rate-limited servers.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
16
|
-
"
|
|
16
|
+
"prebuild": "rimraf dist",
|
|
17
|
+
"build": "rollup -c"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"dist"
|
|
@@ -29,14 +30,15 @@
|
|
|
29
30
|
],
|
|
30
31
|
"author": "Uav1010",
|
|
31
32
|
"license": "MIT",
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@rollup/plugin-typescript": "^11.1.6",
|
|
34
|
-
"rollup": "^4.59.0",
|
|
35
|
-
"tslib": "^2.8.1",
|
|
36
|
-
"tsup": "^8.5.1",
|
|
37
|
-
"typescript": "^5.9.3"
|
|
38
|
-
},
|
|
39
33
|
"engines": {
|
|
40
34
|
"node": ">=18.0.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
38
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
39
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
40
|
+
"rimraf": "^6.1.3",
|
|
41
|
+
"rollup": "^4.59.0",
|
|
42
|
+
"tslib": "^2.8.1"
|
|
41
43
|
}
|
|
42
44
|
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
interface VigorErrorOptions {
|
|
2
|
-
url?: string | null;
|
|
3
|
-
status?: number;
|
|
4
|
-
message?: string;
|
|
5
|
-
data?: any;
|
|
6
|
-
}
|
|
7
|
-
interface VigorFetchConfig {
|
|
8
|
-
path: string;
|
|
9
|
-
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | null;
|
|
10
|
-
offset: RequestInit;
|
|
11
|
-
headers: Record<string, string>;
|
|
12
|
-
body: any;
|
|
13
|
-
count: number;
|
|
14
|
-
max: number;
|
|
15
|
-
wait: number;
|
|
16
|
-
backoff: number;
|
|
17
|
-
unretry: Set<number>;
|
|
18
|
-
retryHeader: string[];
|
|
19
|
-
original: boolean;
|
|
20
|
-
parse: keyof Response | null;
|
|
21
|
-
beforeRequest: Array<(opt: RequestInit) => Promise<Partial<RequestInit> | void> | Partial<RequestInit> | void>;
|
|
22
|
-
afterRequest: Array<(res: Response) => Promise<Response | void> | Response | void>;
|
|
23
|
-
beforeResponse: Array<(res: Response) => Promise<Response> | Response>;
|
|
24
|
-
afterResponse: Array<(data: any) => Promise<any> | any>;
|
|
25
|
-
onError: Array<(err: any) => Promise<any> | any>;
|
|
26
|
-
query: Record<string, any>;
|
|
27
|
-
jitter: number;
|
|
28
|
-
}
|
|
29
|
-
declare class VigorFetch<T = any> {
|
|
30
|
-
private _origin;
|
|
31
|
-
private _config;
|
|
32
|
-
constructor(origin: string, config?: VigorFetchConfig);
|
|
33
|
-
private _next;
|
|
34
|
-
path(arg: string): VigorFetch<T>;
|
|
35
|
-
method(arg: VigorFetchConfig['method']): VigorFetch<T>;
|
|
36
|
-
offset(arg: RequestInit): VigorFetch<T>;
|
|
37
|
-
headers(arg: Record<string, string>): VigorFetch<T>;
|
|
38
|
-
body(arg: any): VigorFetch<T>;
|
|
39
|
-
count(arg: number): VigorFetch<T>;
|
|
40
|
-
max(arg: number): VigorFetch<T>;
|
|
41
|
-
wait(arg: number): VigorFetch<T>;
|
|
42
|
-
backoff(arg: number): VigorFetch<T>;
|
|
43
|
-
unretry(arg: number[]): VigorFetch<T>;
|
|
44
|
-
retryHeader(...arg: string[]): VigorFetch<T>;
|
|
45
|
-
original(arg: boolean): VigorFetch<T>;
|
|
46
|
-
parse(arg: keyof Response): VigorFetch<T>;
|
|
47
|
-
query(arg: Record<string, any>): VigorFetch<T>;
|
|
48
|
-
jitter(arg: number): VigorFetch<T>;
|
|
49
|
-
beforeRequest(...arg: VigorFetchConfig['beforeRequest']): VigorFetch<T>;
|
|
50
|
-
afterRequest(...arg: VigorFetchConfig['afterRequest']): VigorFetch<T>;
|
|
51
|
-
beforeResponse(...arg: VigorFetchConfig['beforeResponse']): VigorFetch<T>;
|
|
52
|
-
afterResponse(...arg: VigorFetchConfig['afterResponse']): VigorFetch<T>;
|
|
53
|
-
onError(...arg: VigorFetchConfig['onError']): VigorFetch<T>;
|
|
54
|
-
request(): Promise<T>;
|
|
55
|
-
}
|
|
56
|
-
interface VigorAllConfig {
|
|
57
|
-
limit: number;
|
|
58
|
-
jitter: number;
|
|
59
|
-
promises: Array<() => Promise<any>>;
|
|
60
|
-
}
|
|
61
|
-
declare class VigorAll {
|
|
62
|
-
private _config;
|
|
63
|
-
constructor(config?: VigorAllConfig);
|
|
64
|
-
private _next;
|
|
65
|
-
limit(arg: number): VigorAll;
|
|
66
|
-
jitter(arg: number): VigorAll;
|
|
67
|
-
promises(...args: Array<() => Promise<any>>): VigorAll;
|
|
68
|
-
request(): Promise<any[]>;
|
|
69
|
-
}
|
|
70
|
-
declare class Vigor {
|
|
71
|
-
fetch<T = any>(origin: string, config?: VigorFetchConfig): VigorFetch<T>;
|
|
72
|
-
all(config?: VigorAllConfig): VigorAll;
|
|
73
|
-
}
|
|
74
|
-
declare const vigor: Vigor;
|
|
75
|
-
|
|
76
|
-
export { type VigorAllConfig, type VigorErrorOptions, type VigorFetchConfig, vigor as default };
|