@gitbeaker/requester-utils 39.33.0 → 39.33.2
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/package.json +4 -13
- package/dist/index.d.mts +0 -125
- package/dist/index.d.ts +0 -125
- package/dist/index.js +0 -238
- package/dist/index.mjs +0 -222
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitbeaker/requester-utils",
|
|
3
|
-
"version": "39.33.
|
|
3
|
+
"version": "39.33.2",
|
|
4
4
|
"description": "Utility functions for requester implementatons used in @gitbeaker",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -43,17 +43,8 @@
|
|
|
43
43
|
"test:types": "tsc",
|
|
44
44
|
"test:integration": "jest --maxWorkers=50% test/integration",
|
|
45
45
|
"test:unit": "jest --maxWorkers=50% test/unit",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"format:src": "prettier '{src,test}/**/*.ts' --ignore-path ../../.prettierignore",
|
|
49
|
-
"format:src:fix": "yarn format:src --write",
|
|
50
|
-
"format": "yarn format:src && yarn format:docs",
|
|
51
|
-
"format:fix": "yarn format:src:fix && yarn format:docs:fix",
|
|
52
|
-
"lint": "eslint '{src,test}/**/*.ts'",
|
|
53
|
-
"lint:fix": "yarn lint --fix",
|
|
54
|
-
"release:rc": "auto next",
|
|
55
|
-
"release:canary": "auto canary",
|
|
56
|
-
"release": "auto shipit"
|
|
46
|
+
"lint": "eslint '**/{src,test,scripts}/**/*.ts'",
|
|
47
|
+
"lint:fix": "yarn lint --fix"
|
|
57
48
|
},
|
|
58
49
|
"dependencies": {
|
|
59
50
|
"picomatch-browser": "^2.2.6",
|
|
@@ -66,5 +57,5 @@
|
|
|
66
57
|
"tsup": "^8.0.1",
|
|
67
58
|
"typescript": "^5.3.3"
|
|
68
59
|
},
|
|
69
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "f09b85042f37a2043db65d21de6dd8cfec424a73"
|
|
70
61
|
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
type RateLimiterFn = () => Promise<number>;
|
|
2
|
-
type RateLimiters = Record<string, RateLimiterFn | {
|
|
3
|
-
method: string;
|
|
4
|
-
limit: RateLimiterFn;
|
|
5
|
-
}>;
|
|
6
|
-
type RateLimitOptions = Record<string, number | {
|
|
7
|
-
method: string;
|
|
8
|
-
limit: number;
|
|
9
|
-
}>;
|
|
10
|
-
type ResponseBodyTypes = Record<string, unknown> | Record<string, unknown>[] | ReadableStream | Blob | string | string[] | number | void | null;
|
|
11
|
-
interface FormattedResponse<T extends ResponseBodyTypes = ResponseBodyTypes> {
|
|
12
|
-
body: T;
|
|
13
|
-
headers: Record<string, string>;
|
|
14
|
-
status: number;
|
|
15
|
-
}
|
|
16
|
-
interface Constructable<T = any> {
|
|
17
|
-
new (...args: any[]): T;
|
|
18
|
-
}
|
|
19
|
-
type ResourceOptions = {
|
|
20
|
-
headers: {
|
|
21
|
-
[header: string]: string;
|
|
22
|
-
};
|
|
23
|
-
authHeaders: {
|
|
24
|
-
[authHeader: string]: () => Promise<string>;
|
|
25
|
-
};
|
|
26
|
-
url: string;
|
|
27
|
-
rejectUnauthorized: boolean;
|
|
28
|
-
rateLimits?: RateLimitOptions;
|
|
29
|
-
};
|
|
30
|
-
type DefaultRequestOptions = {
|
|
31
|
-
body?: FormData | Record<string, unknown>;
|
|
32
|
-
searchParams?: Record<string, unknown>;
|
|
33
|
-
sudo?: string | number;
|
|
34
|
-
method?: string;
|
|
35
|
-
asStream?: boolean;
|
|
36
|
-
signal?: AbortSignal;
|
|
37
|
-
};
|
|
38
|
-
type RequestOptions = {
|
|
39
|
-
headers?: Record<string, string>;
|
|
40
|
-
timeout?: number;
|
|
41
|
-
method?: string;
|
|
42
|
-
searchParams?: string;
|
|
43
|
-
prefixUrl?: string;
|
|
44
|
-
body?: string | FormData;
|
|
45
|
-
asStream?: boolean;
|
|
46
|
-
signal?: AbortSignal;
|
|
47
|
-
rateLimiters?: Record<string, RateLimiterFn>;
|
|
48
|
-
};
|
|
49
|
-
interface RequesterType {
|
|
50
|
-
get<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
51
|
-
post<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
52
|
-
put<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
53
|
-
patch<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
54
|
-
delete<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
55
|
-
}
|
|
56
|
-
type RequestHandlerFn<T extends ResponseBodyTypes = ResponseBodyTypes> = (endpoint: string, options?: Record<string, unknown>) => Promise<FormattedResponse<T>>;
|
|
57
|
-
declare function generateRateLimiterFn(limit: number, interval: number): () => Promise<number>;
|
|
58
|
-
declare function formatQuery(params?: Record<string, unknown>): string;
|
|
59
|
-
type OptionsHandlerFn = (serviceOptions: ResourceOptions, requestOptions: RequestOptions) => Promise<RequestOptions>;
|
|
60
|
-
declare function defaultOptionsHandler(resourceOptions: ResourceOptions, { body, searchParams, sudo, signal, asStream, method, }?: DefaultRequestOptions): Promise<RequestOptions>;
|
|
61
|
-
declare function createRateLimiters(rateLimitOptions?: RateLimitOptions): RateLimiters;
|
|
62
|
-
declare function createRequesterFn(optionsHandler: OptionsHandlerFn, requestHandler: RequestHandlerFn): (serviceOptions: ResourceOptions) => RequesterType;
|
|
63
|
-
declare function presetResourceArguments<T extends Record<string, Constructable>>(resources: T, customConfig?: Record<string, unknown>): T;
|
|
64
|
-
declare function getMatchingRateLimiter(endpoint: string, rateLimiters?: RateLimiters, method?: string): RateLimiterFn;
|
|
65
|
-
|
|
66
|
-
interface RootResourceOptions<C> {
|
|
67
|
-
requesterFn?: (resourceOptions: ResourceOptions) => RequesterType;
|
|
68
|
-
host?: string;
|
|
69
|
-
prefixUrl?: string;
|
|
70
|
-
rejectUnauthorized?: boolean;
|
|
71
|
-
camelize?: C;
|
|
72
|
-
queryTimeout?: number | null;
|
|
73
|
-
sudo?: string | number;
|
|
74
|
-
profileToken?: string;
|
|
75
|
-
profileMode?: 'execution' | 'memory';
|
|
76
|
-
rateLimits?: RateLimitOptions;
|
|
77
|
-
}
|
|
78
|
-
type GitlabToken = string | (() => Promise<string>);
|
|
79
|
-
interface BaseRequestOptionsWithOAuthToken<C> extends RootResourceOptions<C> {
|
|
80
|
-
oauthToken: GitlabToken;
|
|
81
|
-
}
|
|
82
|
-
interface BaseRequestOptionsWithAccessToken<C> extends RootResourceOptions<C> {
|
|
83
|
-
token: GitlabToken;
|
|
84
|
-
}
|
|
85
|
-
interface BaseRequestOptionsWithJobToken<C> extends RootResourceOptions<C> {
|
|
86
|
-
jobToken: GitlabToken;
|
|
87
|
-
}
|
|
88
|
-
type BaseResourceOptions<C> = BaseRequestOptionsWithOAuthToken<C> | BaseRequestOptionsWithAccessToken<C> | BaseRequestOptionsWithJobToken<C>;
|
|
89
|
-
declare class BaseResource<C extends boolean = false> {
|
|
90
|
-
readonly url: string;
|
|
91
|
-
readonly requester: RequesterType;
|
|
92
|
-
readonly queryTimeout: number | null;
|
|
93
|
-
readonly headers: {
|
|
94
|
-
[header: string]: string;
|
|
95
|
-
};
|
|
96
|
-
readonly authHeaders: {
|
|
97
|
-
[authHeader: string]: () => Promise<string>;
|
|
98
|
-
};
|
|
99
|
-
readonly camelize: C | undefined;
|
|
100
|
-
readonly rejectUnauthorized: boolean;
|
|
101
|
-
constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, rateLimits, ...tokens }: BaseResourceOptions<C>);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
declare class GitbeakerRequestError extends Error {
|
|
105
|
-
readonly cause?: {
|
|
106
|
-
description: string;
|
|
107
|
-
request: Request;
|
|
108
|
-
response: Response;
|
|
109
|
-
};
|
|
110
|
-
constructor(message: string, options?: {
|
|
111
|
-
cause?: {
|
|
112
|
-
description: string;
|
|
113
|
-
request: Request;
|
|
114
|
-
response: Response;
|
|
115
|
-
};
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
declare class GitbeakerTimeoutError extends Error {
|
|
119
|
-
constructor(message: string, options?: ErrorOptions);
|
|
120
|
-
}
|
|
121
|
-
declare class GitbeakerRetryError extends Error {
|
|
122
|
-
constructor(message: string, options?: ErrorOptions);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export { type BaseRequestOptionsWithAccessToken, type BaseRequestOptionsWithJobToken, type BaseRequestOptionsWithOAuthToken, BaseResource, type BaseResourceOptions, type Constructable, type DefaultRequestOptions, type FormattedResponse, GitbeakerRequestError, GitbeakerRetryError, GitbeakerTimeoutError, type GitlabToken, type OptionsHandlerFn, type RateLimitOptions, type RateLimiterFn, type RateLimiters, type RequestHandlerFn, type RequestOptions, type RequesterType, type ResourceOptions, type ResponseBodyTypes, type RootResourceOptions, createRateLimiters, createRequesterFn, defaultOptionsHandler, formatQuery, generateRateLimiterFn, getMatchingRateLimiter, presetResourceArguments };
|
package/dist/index.d.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
type RateLimiterFn = () => Promise<number>;
|
|
2
|
-
type RateLimiters = Record<string, RateLimiterFn | {
|
|
3
|
-
method: string;
|
|
4
|
-
limit: RateLimiterFn;
|
|
5
|
-
}>;
|
|
6
|
-
type RateLimitOptions = Record<string, number | {
|
|
7
|
-
method: string;
|
|
8
|
-
limit: number;
|
|
9
|
-
}>;
|
|
10
|
-
type ResponseBodyTypes = Record<string, unknown> | Record<string, unknown>[] | ReadableStream | Blob | string | string[] | number | void | null;
|
|
11
|
-
interface FormattedResponse<T extends ResponseBodyTypes = ResponseBodyTypes> {
|
|
12
|
-
body: T;
|
|
13
|
-
headers: Record<string, string>;
|
|
14
|
-
status: number;
|
|
15
|
-
}
|
|
16
|
-
interface Constructable<T = any> {
|
|
17
|
-
new (...args: any[]): T;
|
|
18
|
-
}
|
|
19
|
-
type ResourceOptions = {
|
|
20
|
-
headers: {
|
|
21
|
-
[header: string]: string;
|
|
22
|
-
};
|
|
23
|
-
authHeaders: {
|
|
24
|
-
[authHeader: string]: () => Promise<string>;
|
|
25
|
-
};
|
|
26
|
-
url: string;
|
|
27
|
-
rejectUnauthorized: boolean;
|
|
28
|
-
rateLimits?: RateLimitOptions;
|
|
29
|
-
};
|
|
30
|
-
type DefaultRequestOptions = {
|
|
31
|
-
body?: FormData | Record<string, unknown>;
|
|
32
|
-
searchParams?: Record<string, unknown>;
|
|
33
|
-
sudo?: string | number;
|
|
34
|
-
method?: string;
|
|
35
|
-
asStream?: boolean;
|
|
36
|
-
signal?: AbortSignal;
|
|
37
|
-
};
|
|
38
|
-
type RequestOptions = {
|
|
39
|
-
headers?: Record<string, string>;
|
|
40
|
-
timeout?: number;
|
|
41
|
-
method?: string;
|
|
42
|
-
searchParams?: string;
|
|
43
|
-
prefixUrl?: string;
|
|
44
|
-
body?: string | FormData;
|
|
45
|
-
asStream?: boolean;
|
|
46
|
-
signal?: AbortSignal;
|
|
47
|
-
rateLimiters?: Record<string, RateLimiterFn>;
|
|
48
|
-
};
|
|
49
|
-
interface RequesterType {
|
|
50
|
-
get<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
51
|
-
post<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
52
|
-
put<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
53
|
-
patch<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
54
|
-
delete<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
|
|
55
|
-
}
|
|
56
|
-
type RequestHandlerFn<T extends ResponseBodyTypes = ResponseBodyTypes> = (endpoint: string, options?: Record<string, unknown>) => Promise<FormattedResponse<T>>;
|
|
57
|
-
declare function generateRateLimiterFn(limit: number, interval: number): () => Promise<number>;
|
|
58
|
-
declare function formatQuery(params?: Record<string, unknown>): string;
|
|
59
|
-
type OptionsHandlerFn = (serviceOptions: ResourceOptions, requestOptions: RequestOptions) => Promise<RequestOptions>;
|
|
60
|
-
declare function defaultOptionsHandler(resourceOptions: ResourceOptions, { body, searchParams, sudo, signal, asStream, method, }?: DefaultRequestOptions): Promise<RequestOptions>;
|
|
61
|
-
declare function createRateLimiters(rateLimitOptions?: RateLimitOptions): RateLimiters;
|
|
62
|
-
declare function createRequesterFn(optionsHandler: OptionsHandlerFn, requestHandler: RequestHandlerFn): (serviceOptions: ResourceOptions) => RequesterType;
|
|
63
|
-
declare function presetResourceArguments<T extends Record<string, Constructable>>(resources: T, customConfig?: Record<string, unknown>): T;
|
|
64
|
-
declare function getMatchingRateLimiter(endpoint: string, rateLimiters?: RateLimiters, method?: string): RateLimiterFn;
|
|
65
|
-
|
|
66
|
-
interface RootResourceOptions<C> {
|
|
67
|
-
requesterFn?: (resourceOptions: ResourceOptions) => RequesterType;
|
|
68
|
-
host?: string;
|
|
69
|
-
prefixUrl?: string;
|
|
70
|
-
rejectUnauthorized?: boolean;
|
|
71
|
-
camelize?: C;
|
|
72
|
-
queryTimeout?: number | null;
|
|
73
|
-
sudo?: string | number;
|
|
74
|
-
profileToken?: string;
|
|
75
|
-
profileMode?: 'execution' | 'memory';
|
|
76
|
-
rateLimits?: RateLimitOptions;
|
|
77
|
-
}
|
|
78
|
-
type GitlabToken = string | (() => Promise<string>);
|
|
79
|
-
interface BaseRequestOptionsWithOAuthToken<C> extends RootResourceOptions<C> {
|
|
80
|
-
oauthToken: GitlabToken;
|
|
81
|
-
}
|
|
82
|
-
interface BaseRequestOptionsWithAccessToken<C> extends RootResourceOptions<C> {
|
|
83
|
-
token: GitlabToken;
|
|
84
|
-
}
|
|
85
|
-
interface BaseRequestOptionsWithJobToken<C> extends RootResourceOptions<C> {
|
|
86
|
-
jobToken: GitlabToken;
|
|
87
|
-
}
|
|
88
|
-
type BaseResourceOptions<C> = BaseRequestOptionsWithOAuthToken<C> | BaseRequestOptionsWithAccessToken<C> | BaseRequestOptionsWithJobToken<C>;
|
|
89
|
-
declare class BaseResource<C extends boolean = false> {
|
|
90
|
-
readonly url: string;
|
|
91
|
-
readonly requester: RequesterType;
|
|
92
|
-
readonly queryTimeout: number | null;
|
|
93
|
-
readonly headers: {
|
|
94
|
-
[header: string]: string;
|
|
95
|
-
};
|
|
96
|
-
readonly authHeaders: {
|
|
97
|
-
[authHeader: string]: () => Promise<string>;
|
|
98
|
-
};
|
|
99
|
-
readonly camelize: C | undefined;
|
|
100
|
-
readonly rejectUnauthorized: boolean;
|
|
101
|
-
constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, rateLimits, ...tokens }: BaseResourceOptions<C>);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
declare class GitbeakerRequestError extends Error {
|
|
105
|
-
readonly cause?: {
|
|
106
|
-
description: string;
|
|
107
|
-
request: Request;
|
|
108
|
-
response: Response;
|
|
109
|
-
};
|
|
110
|
-
constructor(message: string, options?: {
|
|
111
|
-
cause?: {
|
|
112
|
-
description: string;
|
|
113
|
-
request: Request;
|
|
114
|
-
response: Response;
|
|
115
|
-
};
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
declare class GitbeakerTimeoutError extends Error {
|
|
119
|
-
constructor(message: string, options?: ErrorOptions);
|
|
120
|
-
}
|
|
121
|
-
declare class GitbeakerRetryError extends Error {
|
|
122
|
-
constructor(message: string, options?: ErrorOptions);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export { type BaseRequestOptionsWithAccessToken, type BaseRequestOptionsWithJobToken, type BaseRequestOptionsWithOAuthToken, BaseResource, type BaseResourceOptions, type Constructable, type DefaultRequestOptions, type FormattedResponse, GitbeakerRequestError, GitbeakerRetryError, GitbeakerTimeoutError, type GitlabToken, type OptionsHandlerFn, type RateLimitOptions, type RateLimiterFn, type RateLimiters, type RequestHandlerFn, type RequestOptions, type RequesterType, type ResourceOptions, type ResponseBodyTypes, type RootResourceOptions, createRateLimiters, createRequesterFn, defaultOptionsHandler, formatQuery, generateRateLimiterFn, getMatchingRateLimiter, presetResourceArguments };
|
package/dist/index.js
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var qs = require('qs');
|
|
4
|
-
var xcase = require('xcase');
|
|
5
|
-
var rateLimiterFlexible = require('rate-limiter-flexible');
|
|
6
|
-
var Picomatch = require('picomatch-browser');
|
|
7
|
-
|
|
8
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
var Picomatch__default = /*#__PURE__*/_interopDefault(Picomatch);
|
|
11
|
-
|
|
12
|
-
// src/RequesterUtils.ts
|
|
13
|
-
var { isMatch: isGlobMatch } = Picomatch__default.default;
|
|
14
|
-
function generateRateLimiterFn(limit, interval) {
|
|
15
|
-
const limiter = new rateLimiterFlexible.RateLimiterQueue(
|
|
16
|
-
new rateLimiterFlexible.RateLimiterMemory({ points: limit, duration: interval })
|
|
17
|
-
);
|
|
18
|
-
return () => limiter.removeTokens(1);
|
|
19
|
-
}
|
|
20
|
-
function formatQuery(params = {}) {
|
|
21
|
-
const decamelized = xcase.decamelizeKeys(params);
|
|
22
|
-
return qs.stringify(decamelized, { arrayFormat: "brackets" });
|
|
23
|
-
}
|
|
24
|
-
async function defaultOptionsHandler(resourceOptions, {
|
|
25
|
-
body,
|
|
26
|
-
searchParams,
|
|
27
|
-
sudo,
|
|
28
|
-
signal,
|
|
29
|
-
asStream = false,
|
|
30
|
-
method = "GET"
|
|
31
|
-
} = {}) {
|
|
32
|
-
const { headers: preconfiguredHeaders, authHeaders, url } = resourceOptions;
|
|
33
|
-
const headers = { ...preconfiguredHeaders };
|
|
34
|
-
const defaultOptions = {
|
|
35
|
-
method,
|
|
36
|
-
asStream,
|
|
37
|
-
signal,
|
|
38
|
-
prefixUrl: url
|
|
39
|
-
};
|
|
40
|
-
defaultOptions.headers = headers;
|
|
41
|
-
if (sudo)
|
|
42
|
-
defaultOptions.headers.sudo = `${sudo}`;
|
|
43
|
-
if (body) {
|
|
44
|
-
if (body instanceof FormData) {
|
|
45
|
-
defaultOptions.body = body;
|
|
46
|
-
} else {
|
|
47
|
-
defaultOptions.body = JSON.stringify(xcase.decamelizeKeys(body));
|
|
48
|
-
defaultOptions.headers["content-type"] = "application/json";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
const [authHeaderKey, authHeaderFn] = Object.entries(authHeaders)[0];
|
|
52
|
-
defaultOptions.headers[authHeaderKey] = await authHeaderFn();
|
|
53
|
-
const q = formatQuery(searchParams);
|
|
54
|
-
if (q)
|
|
55
|
-
defaultOptions.searchParams = q;
|
|
56
|
-
return Promise.resolve(defaultOptions);
|
|
57
|
-
}
|
|
58
|
-
function createRateLimiters(rateLimitOptions = {}) {
|
|
59
|
-
const rateLimiters = {};
|
|
60
|
-
Object.entries(rateLimitOptions).forEach(([key, config]) => {
|
|
61
|
-
if (typeof config === "number")
|
|
62
|
-
rateLimiters[key] = generateRateLimiterFn(config, 60);
|
|
63
|
-
else
|
|
64
|
-
rateLimiters[key] = {
|
|
65
|
-
method: config.method.toUpperCase(),
|
|
66
|
-
limit: generateRateLimiterFn(config.limit, 60)
|
|
67
|
-
};
|
|
68
|
-
});
|
|
69
|
-
return rateLimiters;
|
|
70
|
-
}
|
|
71
|
-
function createRequesterFn(optionsHandler, requestHandler) {
|
|
72
|
-
const methods = ["get", "post", "put", "patch", "delete"];
|
|
73
|
-
return (serviceOptions) => {
|
|
74
|
-
const requester = {};
|
|
75
|
-
const rateLimiters = createRateLimiters(serviceOptions.rateLimits);
|
|
76
|
-
methods.forEach((m) => {
|
|
77
|
-
requester[m] = async (endpoint, options) => {
|
|
78
|
-
const defaultRequestOptions = await defaultOptionsHandler(serviceOptions, {
|
|
79
|
-
...options,
|
|
80
|
-
method: m.toUpperCase()
|
|
81
|
-
});
|
|
82
|
-
const requestOptions = await optionsHandler(serviceOptions, defaultRequestOptions);
|
|
83
|
-
return requestHandler(endpoint, { ...requestOptions, rateLimiters });
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
return requester;
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function extendClass(Base, customConfig) {
|
|
90
|
-
return class extends Base {
|
|
91
|
-
constructor(...options) {
|
|
92
|
-
const [config, ...opts] = options;
|
|
93
|
-
super({ ...customConfig, ...config }, ...opts);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
function presetResourceArguments(resources, customConfig = {}) {
|
|
98
|
-
const updated = {};
|
|
99
|
-
Object.entries(resources).filter(([, s]) => typeof s === "function").forEach(([k, r]) => {
|
|
100
|
-
updated[k] = extendClass(r, customConfig);
|
|
101
|
-
});
|
|
102
|
-
return updated;
|
|
103
|
-
}
|
|
104
|
-
function getMatchingRateLimiter(endpoint, rateLimiters = {}, method = "GET") {
|
|
105
|
-
const sortedEndpoints = Object.keys(rateLimiters).sort().reverse();
|
|
106
|
-
const match = sortedEndpoints.find((ep) => isGlobMatch(endpoint, ep));
|
|
107
|
-
const rateLimitConfig = match && rateLimiters[match];
|
|
108
|
-
if (typeof rateLimitConfig === "function")
|
|
109
|
-
return rateLimitConfig;
|
|
110
|
-
if (rateLimitConfig && rateLimitConfig?.method?.toUpperCase() === method.toUpperCase()) {
|
|
111
|
-
return rateLimitConfig.limit;
|
|
112
|
-
}
|
|
113
|
-
return generateRateLimiterFn(3e3, 60);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/BaseResource.ts
|
|
117
|
-
function getDynamicToken(tokenArgument) {
|
|
118
|
-
return tokenArgument instanceof Function ? tokenArgument() : Promise.resolve(tokenArgument);
|
|
119
|
-
}
|
|
120
|
-
var DEFAULT_RATE_LIMITS = Object.freeze({
|
|
121
|
-
// Default rate limit
|
|
122
|
-
"**": 3e3,
|
|
123
|
-
// Import/Export
|
|
124
|
-
"projects/import": 6,
|
|
125
|
-
"projects/*/export": 6,
|
|
126
|
-
"projects/*/download": 1,
|
|
127
|
-
"groups/import": 6,
|
|
128
|
-
"groups/*/export": 6,
|
|
129
|
-
"groups/*/download": 1,
|
|
130
|
-
// Note creation
|
|
131
|
-
"projects/*/issues/*/notes": {
|
|
132
|
-
method: "post",
|
|
133
|
-
limit: 300
|
|
134
|
-
},
|
|
135
|
-
"projects/*/snippets/*/notes": {
|
|
136
|
-
method: "post",
|
|
137
|
-
limit: 300
|
|
138
|
-
},
|
|
139
|
-
"projects/*/merge_requests/*/notes": {
|
|
140
|
-
method: "post",
|
|
141
|
-
limit: 300
|
|
142
|
-
},
|
|
143
|
-
"groups/*/epics/*/notes": {
|
|
144
|
-
method: "post",
|
|
145
|
-
limit: 300
|
|
146
|
-
},
|
|
147
|
-
// Repositories - get file archive
|
|
148
|
-
"projects/*/repository/archive*": 5,
|
|
149
|
-
// Project Jobs
|
|
150
|
-
"projects/*/jobs": 600,
|
|
151
|
-
// Member deletion
|
|
152
|
-
"projects/*/members": 60,
|
|
153
|
-
"groups/*/members": 60
|
|
154
|
-
});
|
|
155
|
-
var BaseResource = class {
|
|
156
|
-
url;
|
|
157
|
-
requester;
|
|
158
|
-
queryTimeout;
|
|
159
|
-
headers;
|
|
160
|
-
authHeaders;
|
|
161
|
-
camelize;
|
|
162
|
-
rejectUnauthorized;
|
|
163
|
-
constructor({
|
|
164
|
-
sudo,
|
|
165
|
-
profileToken,
|
|
166
|
-
camelize,
|
|
167
|
-
requesterFn,
|
|
168
|
-
profileMode = "execution",
|
|
169
|
-
host = "https://gitlab.com",
|
|
170
|
-
prefixUrl = "",
|
|
171
|
-
rejectUnauthorized = true,
|
|
172
|
-
queryTimeout = 3e5,
|
|
173
|
-
rateLimits = DEFAULT_RATE_LIMITS,
|
|
174
|
-
...tokens
|
|
175
|
-
}) {
|
|
176
|
-
if (!requesterFn)
|
|
177
|
-
throw new ReferenceError("requesterFn must be passed");
|
|
178
|
-
this.url = [host, "api", "v4", prefixUrl].join("/");
|
|
179
|
-
this.headers = {};
|
|
180
|
-
this.authHeaders = {};
|
|
181
|
-
this.rejectUnauthorized = rejectUnauthorized;
|
|
182
|
-
this.camelize = camelize;
|
|
183
|
-
this.queryTimeout = queryTimeout;
|
|
184
|
-
if ("oauthToken" in tokens)
|
|
185
|
-
this.authHeaders.authorization = async () => {
|
|
186
|
-
const token = await getDynamicToken(tokens.oauthToken);
|
|
187
|
-
return `Bearer ${token}`;
|
|
188
|
-
};
|
|
189
|
-
else if ("jobToken" in tokens)
|
|
190
|
-
this.authHeaders["job-token"] = async () => getDynamicToken(tokens.jobToken);
|
|
191
|
-
else if ("token" in tokens)
|
|
192
|
-
this.authHeaders["private-token"] = async () => getDynamicToken(tokens.token);
|
|
193
|
-
else {
|
|
194
|
-
throw new ReferenceError("A token, oauthToken or jobToken must be passed");
|
|
195
|
-
}
|
|
196
|
-
if (profileToken) {
|
|
197
|
-
this.headers["X-Profile-Token"] = profileToken;
|
|
198
|
-
this.headers["X-Profile-Mode"] = profileMode;
|
|
199
|
-
}
|
|
200
|
-
if (sudo)
|
|
201
|
-
this.headers.Sudo = `${sudo}`;
|
|
202
|
-
this.requester = requesterFn({ ...this, rateLimits });
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// src/GitbeakerError.ts
|
|
207
|
-
var GitbeakerRequestError = class extends Error {
|
|
208
|
-
cause;
|
|
209
|
-
constructor(message, options) {
|
|
210
|
-
super(message, options);
|
|
211
|
-
this.cause = options?.cause;
|
|
212
|
-
this.name = "GitbeakerRequestError";
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
var GitbeakerTimeoutError = class extends Error {
|
|
216
|
-
constructor(message, options) {
|
|
217
|
-
super(message, options);
|
|
218
|
-
this.name = "GitbeakerTimeoutError";
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
var GitbeakerRetryError = class extends Error {
|
|
222
|
-
constructor(message, options) {
|
|
223
|
-
super(message, options);
|
|
224
|
-
this.name = "GitbeakerRetryError";
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
exports.BaseResource = BaseResource;
|
|
229
|
-
exports.GitbeakerRequestError = GitbeakerRequestError;
|
|
230
|
-
exports.GitbeakerRetryError = GitbeakerRetryError;
|
|
231
|
-
exports.GitbeakerTimeoutError = GitbeakerTimeoutError;
|
|
232
|
-
exports.createRateLimiters = createRateLimiters;
|
|
233
|
-
exports.createRequesterFn = createRequesterFn;
|
|
234
|
-
exports.defaultOptionsHandler = defaultOptionsHandler;
|
|
235
|
-
exports.formatQuery = formatQuery;
|
|
236
|
-
exports.generateRateLimiterFn = generateRateLimiterFn;
|
|
237
|
-
exports.getMatchingRateLimiter = getMatchingRateLimiter;
|
|
238
|
-
exports.presetResourceArguments = presetResourceArguments;
|
package/dist/index.mjs
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { stringify } from 'qs';
|
|
2
|
-
import { decamelizeKeys } from 'xcase';
|
|
3
|
-
import { RateLimiterQueue, RateLimiterMemory } from 'rate-limiter-flexible';
|
|
4
|
-
import Picomatch from 'picomatch-browser';
|
|
5
|
-
|
|
6
|
-
// src/RequesterUtils.ts
|
|
7
|
-
var { isMatch: isGlobMatch } = Picomatch;
|
|
8
|
-
function generateRateLimiterFn(limit, interval) {
|
|
9
|
-
const limiter = new RateLimiterQueue(
|
|
10
|
-
new RateLimiterMemory({ points: limit, duration: interval })
|
|
11
|
-
);
|
|
12
|
-
return () => limiter.removeTokens(1);
|
|
13
|
-
}
|
|
14
|
-
function formatQuery(params = {}) {
|
|
15
|
-
const decamelized = decamelizeKeys(params);
|
|
16
|
-
return stringify(decamelized, { arrayFormat: "brackets" });
|
|
17
|
-
}
|
|
18
|
-
async function defaultOptionsHandler(resourceOptions, {
|
|
19
|
-
body,
|
|
20
|
-
searchParams,
|
|
21
|
-
sudo,
|
|
22
|
-
signal,
|
|
23
|
-
asStream = false,
|
|
24
|
-
method = "GET"
|
|
25
|
-
} = {}) {
|
|
26
|
-
const { headers: preconfiguredHeaders, authHeaders, url } = resourceOptions;
|
|
27
|
-
const headers = { ...preconfiguredHeaders };
|
|
28
|
-
const defaultOptions = {
|
|
29
|
-
method,
|
|
30
|
-
asStream,
|
|
31
|
-
signal,
|
|
32
|
-
prefixUrl: url
|
|
33
|
-
};
|
|
34
|
-
defaultOptions.headers = headers;
|
|
35
|
-
if (sudo)
|
|
36
|
-
defaultOptions.headers.sudo = `${sudo}`;
|
|
37
|
-
if (body) {
|
|
38
|
-
if (body instanceof FormData) {
|
|
39
|
-
defaultOptions.body = body;
|
|
40
|
-
} else {
|
|
41
|
-
defaultOptions.body = JSON.stringify(decamelizeKeys(body));
|
|
42
|
-
defaultOptions.headers["content-type"] = "application/json";
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const [authHeaderKey, authHeaderFn] = Object.entries(authHeaders)[0];
|
|
46
|
-
defaultOptions.headers[authHeaderKey] = await authHeaderFn();
|
|
47
|
-
const q = formatQuery(searchParams);
|
|
48
|
-
if (q)
|
|
49
|
-
defaultOptions.searchParams = q;
|
|
50
|
-
return Promise.resolve(defaultOptions);
|
|
51
|
-
}
|
|
52
|
-
function createRateLimiters(rateLimitOptions = {}) {
|
|
53
|
-
const rateLimiters = {};
|
|
54
|
-
Object.entries(rateLimitOptions).forEach(([key, config]) => {
|
|
55
|
-
if (typeof config === "number")
|
|
56
|
-
rateLimiters[key] = generateRateLimiterFn(config, 60);
|
|
57
|
-
else
|
|
58
|
-
rateLimiters[key] = {
|
|
59
|
-
method: config.method.toUpperCase(),
|
|
60
|
-
limit: generateRateLimiterFn(config.limit, 60)
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
return rateLimiters;
|
|
64
|
-
}
|
|
65
|
-
function createRequesterFn(optionsHandler, requestHandler) {
|
|
66
|
-
const methods = ["get", "post", "put", "patch", "delete"];
|
|
67
|
-
return (serviceOptions) => {
|
|
68
|
-
const requester = {};
|
|
69
|
-
const rateLimiters = createRateLimiters(serviceOptions.rateLimits);
|
|
70
|
-
methods.forEach((m) => {
|
|
71
|
-
requester[m] = async (endpoint, options) => {
|
|
72
|
-
const defaultRequestOptions = await defaultOptionsHandler(serviceOptions, {
|
|
73
|
-
...options,
|
|
74
|
-
method: m.toUpperCase()
|
|
75
|
-
});
|
|
76
|
-
const requestOptions = await optionsHandler(serviceOptions, defaultRequestOptions);
|
|
77
|
-
return requestHandler(endpoint, { ...requestOptions, rateLimiters });
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
return requester;
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function extendClass(Base, customConfig) {
|
|
84
|
-
return class extends Base {
|
|
85
|
-
constructor(...options) {
|
|
86
|
-
const [config, ...opts] = options;
|
|
87
|
-
super({ ...customConfig, ...config }, ...opts);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
function presetResourceArguments(resources, customConfig = {}) {
|
|
92
|
-
const updated = {};
|
|
93
|
-
Object.entries(resources).filter(([, s]) => typeof s === "function").forEach(([k, r]) => {
|
|
94
|
-
updated[k] = extendClass(r, customConfig);
|
|
95
|
-
});
|
|
96
|
-
return updated;
|
|
97
|
-
}
|
|
98
|
-
function getMatchingRateLimiter(endpoint, rateLimiters = {}, method = "GET") {
|
|
99
|
-
const sortedEndpoints = Object.keys(rateLimiters).sort().reverse();
|
|
100
|
-
const match = sortedEndpoints.find((ep) => isGlobMatch(endpoint, ep));
|
|
101
|
-
const rateLimitConfig = match && rateLimiters[match];
|
|
102
|
-
if (typeof rateLimitConfig === "function")
|
|
103
|
-
return rateLimitConfig;
|
|
104
|
-
if (rateLimitConfig && rateLimitConfig?.method?.toUpperCase() === method.toUpperCase()) {
|
|
105
|
-
return rateLimitConfig.limit;
|
|
106
|
-
}
|
|
107
|
-
return generateRateLimiterFn(3e3, 60);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/BaseResource.ts
|
|
111
|
-
function getDynamicToken(tokenArgument) {
|
|
112
|
-
return tokenArgument instanceof Function ? tokenArgument() : Promise.resolve(tokenArgument);
|
|
113
|
-
}
|
|
114
|
-
var DEFAULT_RATE_LIMITS = Object.freeze({
|
|
115
|
-
// Default rate limit
|
|
116
|
-
"**": 3e3,
|
|
117
|
-
// Import/Export
|
|
118
|
-
"projects/import": 6,
|
|
119
|
-
"projects/*/export": 6,
|
|
120
|
-
"projects/*/download": 1,
|
|
121
|
-
"groups/import": 6,
|
|
122
|
-
"groups/*/export": 6,
|
|
123
|
-
"groups/*/download": 1,
|
|
124
|
-
// Note creation
|
|
125
|
-
"projects/*/issues/*/notes": {
|
|
126
|
-
method: "post",
|
|
127
|
-
limit: 300
|
|
128
|
-
},
|
|
129
|
-
"projects/*/snippets/*/notes": {
|
|
130
|
-
method: "post",
|
|
131
|
-
limit: 300
|
|
132
|
-
},
|
|
133
|
-
"projects/*/merge_requests/*/notes": {
|
|
134
|
-
method: "post",
|
|
135
|
-
limit: 300
|
|
136
|
-
},
|
|
137
|
-
"groups/*/epics/*/notes": {
|
|
138
|
-
method: "post",
|
|
139
|
-
limit: 300
|
|
140
|
-
},
|
|
141
|
-
// Repositories - get file archive
|
|
142
|
-
"projects/*/repository/archive*": 5,
|
|
143
|
-
// Project Jobs
|
|
144
|
-
"projects/*/jobs": 600,
|
|
145
|
-
// Member deletion
|
|
146
|
-
"projects/*/members": 60,
|
|
147
|
-
"groups/*/members": 60
|
|
148
|
-
});
|
|
149
|
-
var BaseResource = class {
|
|
150
|
-
url;
|
|
151
|
-
requester;
|
|
152
|
-
queryTimeout;
|
|
153
|
-
headers;
|
|
154
|
-
authHeaders;
|
|
155
|
-
camelize;
|
|
156
|
-
rejectUnauthorized;
|
|
157
|
-
constructor({
|
|
158
|
-
sudo,
|
|
159
|
-
profileToken,
|
|
160
|
-
camelize,
|
|
161
|
-
requesterFn,
|
|
162
|
-
profileMode = "execution",
|
|
163
|
-
host = "https://gitlab.com",
|
|
164
|
-
prefixUrl = "",
|
|
165
|
-
rejectUnauthorized = true,
|
|
166
|
-
queryTimeout = 3e5,
|
|
167
|
-
rateLimits = DEFAULT_RATE_LIMITS,
|
|
168
|
-
...tokens
|
|
169
|
-
}) {
|
|
170
|
-
if (!requesterFn)
|
|
171
|
-
throw new ReferenceError("requesterFn must be passed");
|
|
172
|
-
this.url = [host, "api", "v4", prefixUrl].join("/");
|
|
173
|
-
this.headers = {};
|
|
174
|
-
this.authHeaders = {};
|
|
175
|
-
this.rejectUnauthorized = rejectUnauthorized;
|
|
176
|
-
this.camelize = camelize;
|
|
177
|
-
this.queryTimeout = queryTimeout;
|
|
178
|
-
if ("oauthToken" in tokens)
|
|
179
|
-
this.authHeaders.authorization = async () => {
|
|
180
|
-
const token = await getDynamicToken(tokens.oauthToken);
|
|
181
|
-
return `Bearer ${token}`;
|
|
182
|
-
};
|
|
183
|
-
else if ("jobToken" in tokens)
|
|
184
|
-
this.authHeaders["job-token"] = async () => getDynamicToken(tokens.jobToken);
|
|
185
|
-
else if ("token" in tokens)
|
|
186
|
-
this.authHeaders["private-token"] = async () => getDynamicToken(tokens.token);
|
|
187
|
-
else {
|
|
188
|
-
throw new ReferenceError("A token, oauthToken or jobToken must be passed");
|
|
189
|
-
}
|
|
190
|
-
if (profileToken) {
|
|
191
|
-
this.headers["X-Profile-Token"] = profileToken;
|
|
192
|
-
this.headers["X-Profile-Mode"] = profileMode;
|
|
193
|
-
}
|
|
194
|
-
if (sudo)
|
|
195
|
-
this.headers.Sudo = `${sudo}`;
|
|
196
|
-
this.requester = requesterFn({ ...this, rateLimits });
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
// src/GitbeakerError.ts
|
|
201
|
-
var GitbeakerRequestError = class extends Error {
|
|
202
|
-
cause;
|
|
203
|
-
constructor(message, options) {
|
|
204
|
-
super(message, options);
|
|
205
|
-
this.cause = options?.cause;
|
|
206
|
-
this.name = "GitbeakerRequestError";
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
var GitbeakerTimeoutError = class extends Error {
|
|
210
|
-
constructor(message, options) {
|
|
211
|
-
super(message, options);
|
|
212
|
-
this.name = "GitbeakerTimeoutError";
|
|
213
|
-
}
|
|
214
|
-
};
|
|
215
|
-
var GitbeakerRetryError = class extends Error {
|
|
216
|
-
constructor(message, options) {
|
|
217
|
-
super(message, options);
|
|
218
|
-
this.name = "GitbeakerRetryError";
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
export { BaseResource, GitbeakerRequestError, GitbeakerRetryError, GitbeakerTimeoutError, createRateLimiters, createRequesterFn, defaultOptionsHandler, formatQuery, generateRateLimiterFn, getMatchingRateLimiter, presetResourceArguments };
|