@gitbeaker/requester-utils
Advanced tools
Comparing version 39.18.0 to 39.19.0
@@ -0,1 +1,11 @@ | ||
import { RateLimit } from 'async-sema'; | ||
type RateLimiters = Record<string, ReturnType<typeof RateLimit> | { | ||
method: string; | ||
limit: ReturnType<typeof RateLimit>; | ||
}>; | ||
type RateLimitOptions = Record<string, number | { | ||
method: string; | ||
limit: number; | ||
}>; | ||
type ResponseBodyTypes = Record<string, unknown> | Record<string, unknown>[] | ReadableStream | Blob | string | string[] | number | void | null; | ||
@@ -19,2 +29,3 @@ interface FormattedResponse<T extends ResponseBodyTypes = ResponseBodyTypes> { | ||
rejectUnauthorized: boolean; | ||
rateLimits?: RateLimitOptions; | ||
}; | ||
@@ -38,2 +49,3 @@ type DefaultRequestOptions = { | ||
signal?: AbortSignal; | ||
rateLimiters?: Record<string, ReturnType<typeof RateLimit>>; | ||
}; | ||
@@ -47,8 +59,10 @@ interface RequesterType { | ||
} | ||
type RequestHandlerFn<T extends ResponseBodyTypes = ResponseBodyTypes> = (endpoint: string, options?: Record<string, unknown>) => Promise<FormattedResponse<T>>; | ||
declare function formatQuery(params?: Record<string, unknown>): string; | ||
type OptionsHandlerFn = (serviceOptions: ResourceOptions, requestOptions: RequestOptions) => Promise<RequestOptions>; | ||
declare function defaultOptionsHandler(resourceOptions: ResourceOptions, { body, searchParams, sudo, signal, asStream, method, }?: DefaultRequestOptions): Promise<RequestOptions>; | ||
type RequestHandlerFn<T extends ResponseBodyTypes = ResponseBodyTypes> = (endpoint: string, options?: Record<string, unknown>) => Promise<FormattedResponse<T>>; | ||
declare function createRateLimiters(rateLimitOptions?: RateLimitOptions): RateLimiters; | ||
declare function createRequesterFn(optionsHandler: OptionsHandlerFn, requestHandler: RequestHandlerFn): (serviceOptions: ResourceOptions) => RequesterType; | ||
declare function presetResourceArguments<T extends Record<string, Constructable>>(resources: T, customConfig?: Record<string, unknown>): T; | ||
declare function getMatchingRateLimiter(endpoint: string, rateLimiters?: RateLimiters, method?: string): () => Promise<void>; | ||
@@ -65,2 +79,3 @@ interface RootResourceOptions<C> { | ||
profileMode?: 'execution' | 'memory'; | ||
rateLimits?: RateLimitOptions; | ||
} | ||
@@ -90,5 +105,5 @@ type GitlabToken = string | (() => Promise<string>); | ||
readonly rejectUnauthorized: boolean; | ||
constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, ...tokens }: BaseResourceOptions<C>); | ||
constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, rateLimits, ...tokens }: BaseResourceOptions<C>); | ||
} | ||
export { BaseRequestOptionsWithAccessToken, BaseRequestOptionsWithJobToken, BaseRequestOptionsWithOAuthToken, BaseResource, BaseResourceOptions, Constructable, DefaultRequestOptions, FormattedResponse, GitlabToken, OptionsHandlerFn, RequestHandlerFn, RequestOptions, RequesterType, ResourceOptions, ResponseBodyTypes, RootResourceOptions, createRequesterFn, defaultOptionsHandler, formatQuery, presetResourceArguments }; | ||
export { BaseRequestOptionsWithAccessToken, BaseRequestOptionsWithJobToken, BaseRequestOptionsWithOAuthToken, BaseResource, BaseResourceOptions, Constructable, DefaultRequestOptions, FormattedResponse, GitlabToken, OptionsHandlerFn, RateLimitOptions, RateLimiters, RequestHandlerFn, RequestOptions, RequesterType, ResourceOptions, ResponseBodyTypes, RootResourceOptions, createRateLimiters, createRequesterFn, defaultOptionsHandler, formatQuery, getMatchingRateLimiter, presetResourceArguments }; |
@@ -5,3 +5,9 @@ 'use strict'; | ||
var xcase = require('xcase'); | ||
var asyncSema = require('async-sema'); | ||
var micromatch = require('micromatch'); | ||
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } | ||
var micromatch__default = /*#__PURE__*/_interopDefault(micromatch); | ||
// src/RequesterUtils.ts | ||
@@ -49,2 +55,15 @@ function formatQuery(params = {}) { | ||
} | ||
function createRateLimiters(rateLimitOptions = {}) { | ||
const rateLimiters = {}; | ||
Object.entries(rateLimitOptions).forEach(([key, config]) => { | ||
if (typeof config === "number") | ||
rateLimiters[key] = asyncSema.RateLimit(config, { timeUnit: 6e4 }); | ||
else | ||
rateLimiters[key] = { | ||
method: config.method.toUpperCase(), | ||
limit: asyncSema.RateLimit(config.limit, { timeUnit: 6e4 }) | ||
}; | ||
}); | ||
return rateLimiters; | ||
} | ||
function createRequesterFn(optionsHandler, requestHandler) { | ||
@@ -54,2 +73,3 @@ const methods = ["get", "post", "put", "patch", "delete"]; | ||
const requester = {}; | ||
const rateLimiters = createRateLimiters(serviceOptions.rateLimits); | ||
methods.forEach((m) => { | ||
@@ -62,3 +82,3 @@ requester[m] = async (endpoint, options) => { | ||
const requestOptions = await optionsHandler(serviceOptions, defaultRequestOptions); | ||
return requestHandler(endpoint, requestOptions); | ||
return requestHandler(endpoint, { ...requestOptions, rateLimiters }); | ||
}; | ||
@@ -69,3 +89,3 @@ }); | ||
} | ||
function extendClass(Base, customConfig = {}) { | ||
function extendClass(Base, customConfig) { | ||
return class extends Base { | ||
@@ -85,2 +105,14 @@ constructor(...options) { | ||
} | ||
function getMatchingRateLimiter(endpoint, rateLimiters = {}, method = "GET") { | ||
const sortedEndpoints = Object.keys(rateLimiters).sort().reverse(); | ||
const match = sortedEndpoints.find((ep) => micromatch__default.default.isMatch(endpoint, ep)); | ||
const rateLimitConfig = match && rateLimiters[match]; | ||
if (rateLimitConfig && typeof rateLimitConfig !== "object") { | ||
return rateLimitConfig; | ||
} | ||
if (rateLimitConfig && rateLimitConfig.method.toUpperCase() === method.toUpperCase()) { | ||
return rateLimitConfig.limit; | ||
} | ||
return asyncSema.RateLimit(3e3, { timeUnit: 6e4 }); | ||
} | ||
@@ -91,2 +123,37 @@ // src/BaseResource.ts | ||
} | ||
var DEFAULT_RATE_LIMITS = Object.freeze({ | ||
// Default rate limit | ||
"**": 3e3, | ||
// Import/Export | ||
"projects/import": 6, | ||
"projects/*/export": 6, | ||
"projects/*/download": 1, | ||
"groups/import": 6, | ||
"groups/*/export": 6, | ||
"groups/*/download": 1, | ||
// Note creation | ||
"projects/*/issues/*/notes": { | ||
method: "post", | ||
limit: 300 | ||
}, | ||
"projects/*/snippets/*/notes": { | ||
method: "post", | ||
limit: 300 | ||
}, | ||
"projects/*/merge_requests/*/notes": { | ||
method: "post", | ||
limit: 300 | ||
}, | ||
"groups/*/epics/*/notes": { | ||
method: "post", | ||
limit: 300 | ||
}, | ||
// Repositories - get file archive | ||
"projects/*/repository/archive*": 5, | ||
// Project Jobs | ||
"projects/*/jobs": 600, | ||
// Member deletion | ||
"projects/*/members": 60, | ||
"groups/*/members": 60 | ||
}); | ||
var BaseResource = class { | ||
@@ -110,2 +177,3 @@ url; | ||
queryTimeout = 3e5, | ||
rateLimits = DEFAULT_RATE_LIMITS, | ||
...tokens | ||
@@ -139,3 +207,3 @@ }) { | ||
this.headers.Sudo = `${sudo}`; | ||
this.requester = requesterFn({ ...this }); | ||
this.requester = requesterFn({ ...this, rateLimits }); | ||
} | ||
@@ -145,5 +213,7 @@ }; | ||
exports.BaseResource = BaseResource; | ||
exports.createRateLimiters = createRateLimiters; | ||
exports.createRequesterFn = createRequesterFn; | ||
exports.defaultOptionsHandler = defaultOptionsHandler; | ||
exports.formatQuery = formatQuery; | ||
exports.getMatchingRateLimiter = getMatchingRateLimiter; | ||
exports.presetResourceArguments = presetResourceArguments; |
{ | ||
"name": "@gitbeaker/requester-utils", | ||
"version": "39.18.0", | ||
"version": "39.19.0", | ||
"description": "Utility functions for requester implementatons used in @gitbeaker", | ||
@@ -54,2 +54,4 @@ "license": "MIT", | ||
"dependencies": { | ||
"async-sema": "^3.1.1", | ||
"micromatch": "^4.0.5", | ||
"qs": "^6.11.2", | ||
@@ -63,3 +65,3 @@ "xcase": "^2.0.1" | ||
}, | ||
"gitHead": "41b250e761aa15d8605c50b76d8439af827e06b5" | ||
"gitHead": "b6ac7ead7ee50ced0f99f66ea0c212d2afcba3c2" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55110
499
4
+ Addedasync-sema@^3.1.1
+ Addedmicromatch@^4.0.5
+ Addedasync-sema@3.1.1(transitive)
+ Addedbraces@3.0.3(transitive)
+ Addedfill-range@7.1.1(transitive)
+ Addedis-number@7.0.0(transitive)
+ Addedmicromatch@4.0.8(transitive)
+ Addedpicomatch@2.3.1(transitive)
+ Addedto-regex-range@5.0.1(transitive)