@gitbeaker/rest 39.18.0 → 39.19.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 +68 -0
- package/dist/index.js +4 -2
- package/dist/index.mjs +5 -3
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
- [API Client](#api-client)
|
|
77
77
|
- [Expanded Payloads](#expanded-payloads)
|
|
78
78
|
- [Pagination](#pagination)
|
|
79
|
+
- [Rate Limits](#rate-limits)
|
|
79
80
|
- [Error Handling](#error-handling)
|
|
80
81
|
- [Examples](#examples)
|
|
81
82
|
- [Testing](../../docs/TESTING.md)
|
|
@@ -155,6 +156,7 @@ Available instantiating options:
|
|
|
155
156
|
| `queryTimeout` | Yes | `300000` | Query Timeout in ms |
|
|
156
157
|
| `profileToken` | Yes | N/A | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
|
|
157
158
|
| `profileMode` | Yes | `execution` | [Requests Profiles Token](https://docs.gitlab.com/ee/administration/monitoring/performance/request_profiling.html) |
|
|
159
|
+
| `rateLimits` | No | [DEFAULT_RATE_LIMITS](#rate-limits) | Global and endpoint specific adjustable rate limits |
|
|
158
160
|
|
|
159
161
|
> \*One of these options must be supplied.
|
|
160
162
|
|
|
@@ -267,6 +269,72 @@ const { data } = await api.Projects.all({
|
|
|
267
269
|
});
|
|
268
270
|
```
|
|
269
271
|
|
|
272
|
+
### Rate Limits
|
|
273
|
+
|
|
274
|
+
Rate limits are completely customizable, and are used to limit the request rate between consecutive API requests within the library. By default, all non-specified endpoints use a 3000 rps rate limit, while some endpoints have much smaller rates as dictated by the [Gitlab Docs](https://docs.gitlab.com/ee/security/rate_limits.html). See below for the default values:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
const DEFAULT_RATE_LIMITS = Object.freeze({
|
|
278
|
+
// Default rate limit
|
|
279
|
+
'**': 3000,
|
|
280
|
+
|
|
281
|
+
// Import/Export
|
|
282
|
+
'projects/import': 6,
|
|
283
|
+
'projects/*/export': 6,
|
|
284
|
+
'projects/*/download': 1,
|
|
285
|
+
'groups/import': 6,
|
|
286
|
+
'groups/*/export': 6,
|
|
287
|
+
'groups/*/download': 1,
|
|
288
|
+
|
|
289
|
+
// Note creation
|
|
290
|
+
'projects/*/issues/*/notes': {
|
|
291
|
+
method: 'post',
|
|
292
|
+
limit: 300,
|
|
293
|
+
},
|
|
294
|
+
'projects/*/snippets/*/notes': {
|
|
295
|
+
method: 'post',
|
|
296
|
+
limit: 300,
|
|
297
|
+
},
|
|
298
|
+
'projects/*/merge_requests/*/notes': {
|
|
299
|
+
method: 'post',
|
|
300
|
+
limit: 300,
|
|
301
|
+
},
|
|
302
|
+
'groups/*/epics/*/notes': {
|
|
303
|
+
method: 'post',
|
|
304
|
+
limit: 300,
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
// Repositories - get file archive
|
|
308
|
+
'projects/*/repository/archive*': 5,
|
|
309
|
+
|
|
310
|
+
// Project Jobs
|
|
311
|
+
'projects/*/jobs': 600,
|
|
312
|
+
|
|
313
|
+
// Member deletion
|
|
314
|
+
'projects/*/members': 60,
|
|
315
|
+
'groups/*/members': 60,
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Rate limits can be overridden when instantiating a API wrapper. For ease of use, these limits are configured using glob patterns, and can be formatted in two ways.
|
|
320
|
+
|
|
321
|
+
1. The glob for the endpoint with the corresponding rate per second
|
|
322
|
+
2. The glob for the endpoint, with an object specifying the specific method for the endpoint and the corresponding rate limit
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
const api = new Gitlab({
|
|
326
|
+
token: 'token',
|
|
327
|
+
rateLimits: {
|
|
328
|
+
'**': 30,
|
|
329
|
+
'projects/import/*': 40,
|
|
330
|
+
'projects/*/issues/*/notes': {
|
|
331
|
+
method: 'post',
|
|
332
|
+
limit: 300,
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
270
338
|
### Error Handling
|
|
271
339
|
|
|
272
340
|
Request errors are returned back within a plain Error instance, using the cause to hold the original response and a text description of the error pulled from the response's error or message fields if JSON, or its plain text value:
|
package/dist/index.js
CHANGED
|
@@ -88,7 +88,8 @@ function getConditionalMode(endpoint) {
|
|
|
88
88
|
async function defaultRequestHandler(endpoint, options) {
|
|
89
89
|
const retryCodes = [429, 502];
|
|
90
90
|
const maxRetries = 10;
|
|
91
|
-
const { prefixUrl, asStream, searchParams, ...opts } = options || {};
|
|
91
|
+
const { prefixUrl, asStream, searchParams, rateLimiters, method, ...opts } = options || {};
|
|
92
|
+
const endpointRateLimit = requesterUtils.getMatchingRateLimiter(endpoint, rateLimiters, method);
|
|
92
93
|
let baseUrl;
|
|
93
94
|
if (prefixUrl)
|
|
94
95
|
baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
|
|
@@ -96,7 +97,8 @@ async function defaultRequestHandler(endpoint, options) {
|
|
|
96
97
|
url.search = searchParams || "";
|
|
97
98
|
const mode = getConditionalMode(endpoint);
|
|
98
99
|
for (let i = 0; i < maxRetries; i += 1) {
|
|
99
|
-
const request = new Request(url, { ...opts, mode });
|
|
100
|
+
const request = new Request(url, { ...opts, method, mode });
|
|
101
|
+
await endpointRateLimit();
|
|
100
102
|
const response = await fetch(request).catch((e) => {
|
|
101
103
|
if (e.name === "TimeoutError" || e.name === "AbortError") {
|
|
102
104
|
throw new Error("Query timeout was reached");
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Resources from '@gitbeaker/core';
|
|
2
|
-
import { createRequesterFn, presetResourceArguments } from '@gitbeaker/requester-utils';
|
|
2
|
+
import { createRequesterFn, presetResourceArguments, getMatchingRateLimiter } from '@gitbeaker/requester-utils';
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
5
|
async function defaultOptionsHandler(resourceOptions, requestOptions) {
|
|
@@ -66,7 +66,8 @@ function getConditionalMode(endpoint) {
|
|
|
66
66
|
async function defaultRequestHandler(endpoint, options) {
|
|
67
67
|
const retryCodes = [429, 502];
|
|
68
68
|
const maxRetries = 10;
|
|
69
|
-
const { prefixUrl, asStream, searchParams, ...opts } = options || {};
|
|
69
|
+
const { prefixUrl, asStream, searchParams, rateLimiters, method, ...opts } = options || {};
|
|
70
|
+
const endpointRateLimit = getMatchingRateLimiter(endpoint, rateLimiters, method);
|
|
70
71
|
let baseUrl;
|
|
71
72
|
if (prefixUrl)
|
|
72
73
|
baseUrl = prefixUrl.endsWith("/") ? prefixUrl : `${prefixUrl}/`;
|
|
@@ -74,7 +75,8 @@ async function defaultRequestHandler(endpoint, options) {
|
|
|
74
75
|
url.search = searchParams || "";
|
|
75
76
|
const mode = getConditionalMode(endpoint);
|
|
76
77
|
for (let i = 0; i < maxRetries; i += 1) {
|
|
77
|
-
const request = new Request(url, { ...opts, mode });
|
|
78
|
+
const request = new Request(url, { ...opts, method, mode });
|
|
79
|
+
await endpointRateLimit();
|
|
78
80
|
const response = await fetch(request).catch((e) => {
|
|
79
81
|
if (e.name === "TimeoutError" || e.name === "AbortError") {
|
|
80
82
|
throw new Error("Query timeout was reached");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitbeaker/rest",
|
|
3
|
-
"version": "39.
|
|
3
|
+
"version": "39.19.0",
|
|
4
4
|
"description": "Cross Platform implementation of the GitLab API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"test:types": "tsc",
|
|
41
41
|
"test:e2e:browser": "playwright test",
|
|
42
42
|
"test:e2e": "yarn test:e2e:browser",
|
|
43
|
-
"test:integration:nodejs": "jest --maxWorkers=50% test/integration/nodejs",
|
|
43
|
+
"test:integration:nodejs": "jest --maxWorkers=50% test/integration/nodejs/resources/Issues.ts",
|
|
44
44
|
"test:integration": "yarn test:integration:nodejs",
|
|
45
45
|
"test:unit": "jest --maxWorkers=50% test/unit",
|
|
46
46
|
"format:docs": "prettier '**/(*.json|.yml|.js|.md)' --ignore-path ../../.prettierignore",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"release": "auto shipit"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@gitbeaker/core": "^39.
|
|
60
|
-
"@gitbeaker/requester-utils": "^39.
|
|
59
|
+
"@gitbeaker/core": "^39.19.0",
|
|
60
|
+
"@gitbeaker/requester-utils": "^39.19.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@playwright/test": "^1.35.1",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"tsup": "^7.1.0",
|
|
66
66
|
"typescript": "^5.1.6"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "b6ac7ead7ee50ced0f99f66ea0c212d2afcba3c2"
|
|
69
69
|
}
|