@gitbeaker/requester-utils 39.1.1 → 39.3.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 CHANGED
@@ -225,6 +225,7 @@ import { RequesterUtils, BaseResource } from '@gitbeaker/requester-utils';
225
225
  <td align="center" valign="top" width="3.84%"><a href="https://simonecorsi.dev/"><img src="https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/5617452?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="Simone Corsi"/></td>
226
226
  <td align="center" valign="top" width="3.84%"><a href="https://github.com/Bambii556"><img src="https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/34485027?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="Bambii"/></td>
227
227
  <td align="center" valign="top" width="3.84%"><a href="https://github.com/ravewill"><img src="https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/128541928?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="Will"/></td>
228
+ <td align="center" valign="top" width="3.84%"><a href="https://github.com/ArnaudTA"><img src="https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/33383276?v=4&h=25&w=25&fit=cover&mask=circle&maxage=7d" alt="ArnaudTA"/></td>
228
229
  </tr>
229
230
  </p>
230
231
 
@@ -0,0 +1,89 @@
1
+ type ResponseBodyTypes = Record<string, unknown> | Record<string, unknown>[] | ReadableStream | Blob | string | string[] | number | void | null;
2
+ interface FormattedResponse<T extends ResponseBodyTypes = ResponseBodyTypes> {
3
+ body: T;
4
+ headers: Record<string, string>;
5
+ status: number;
6
+ }
7
+ interface Constructable<T = any> {
8
+ new (...args: any[]): T;
9
+ }
10
+ type DefaultResourceOptions = {
11
+ headers: {
12
+ [header: string]: string;
13
+ };
14
+ authHeaders: {
15
+ [authHeader: string]: () => Promise<string>;
16
+ };
17
+ url: string;
18
+ rejectUnauthorized: boolean;
19
+ };
20
+ type DefaultRequestOptions = {
21
+ body?: FormData | Record<string, unknown>;
22
+ searchParams?: Record<string, unknown>;
23
+ sudo?: string | number;
24
+ method?: string;
25
+ asStream?: boolean;
26
+ signal?: AbortSignal;
27
+ };
28
+ type RequestOptions = {
29
+ headers: Record<string, string>;
30
+ timeout?: number;
31
+ method: string;
32
+ searchParams?: string;
33
+ prefixUrl: string;
34
+ body?: string | FormData;
35
+ asStream?: boolean;
36
+ signal?: AbortSignal;
37
+ };
38
+ interface RequesterType {
39
+ get<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
40
+ post<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
41
+ put<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
42
+ patch<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
43
+ delete<T extends ResponseBodyTypes>(endpoint: string, options?: DefaultRequestOptions): Promise<FormattedResponse<T>>;
44
+ }
45
+ declare function formatQuery(params?: Record<string, unknown>): string;
46
+ type OptionsHandlerFn = (serviceOptions: DefaultResourceOptions, requestOptions: DefaultRequestOptions) => Promise<RequestOptions>;
47
+ declare function defaultOptionsHandler(resourceOptions: DefaultResourceOptions, { body, searchParams, sudo, signal, asStream, method, }?: DefaultRequestOptions): Promise<RequestOptions>;
48
+ type RequestHandlerFn<T extends ResponseBodyTypes = ResponseBodyTypes> = (endpoint: string, options?: Record<string, unknown>) => Promise<FormattedResponse<T>>;
49
+ declare function createRequesterFn(optionsHandler: OptionsHandlerFn, requestHandler: RequestHandlerFn): (serviceOptions: DefaultResourceOptions) => RequesterType;
50
+ declare function presetResourceArguments<T extends Record<string, Constructable>>(resources: T, customConfig?: Record<string, unknown>): T;
51
+
52
+ interface RootResourceOptions<C> {
53
+ requesterFn?: (resourceOptions: DefaultResourceOptions) => RequesterType;
54
+ host?: string;
55
+ prefixUrl?: string;
56
+ rejectUnauthorized?: boolean;
57
+ camelize?: C;
58
+ queryTimeout?: number | null;
59
+ sudo?: string | number;
60
+ profileToken?: string;
61
+ profileMode?: 'execution' | 'memory';
62
+ }
63
+ type GitlabToken = string | (() => Promise<string>);
64
+ interface BaseRequestOptionsWithOAuthToken<C> extends RootResourceOptions<C> {
65
+ oauthToken: GitlabToken;
66
+ }
67
+ interface BaseRequestOptionsWithAccessToken<C> extends RootResourceOptions<C> {
68
+ token: GitlabToken;
69
+ }
70
+ interface BaseRequestOptionsWithJobToken<C> extends RootResourceOptions<C> {
71
+ jobToken: GitlabToken;
72
+ }
73
+ type BaseResourceOptions<C> = BaseRequestOptionsWithOAuthToken<C> | BaseRequestOptionsWithAccessToken<C> | BaseRequestOptionsWithJobToken<C>;
74
+ declare class BaseResource<C extends boolean = false> {
75
+ readonly url: string;
76
+ readonly requester: RequesterType;
77
+ readonly queryTimeout: number | null;
78
+ readonly headers: {
79
+ [header: string]: string;
80
+ };
81
+ readonly authHeaders: {
82
+ [authHeader: string]: () => Promise<string>;
83
+ };
84
+ readonly camelize: C | undefined;
85
+ readonly rejectUnauthorized: boolean;
86
+ constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, ...tokens }: BaseResourceOptions<C>);
87
+ }
88
+
89
+ export { BaseRequestOptionsWithAccessToken, BaseRequestOptionsWithJobToken, BaseRequestOptionsWithOAuthToken, BaseResource, BaseResourceOptions, Constructable, DefaultRequestOptions, DefaultResourceOptions, FormattedResponse, GitlabToken, OptionsHandlerFn, RequestHandlerFn, RequestOptions, RequesterType, ResponseBodyTypes, RootResourceOptions, createRequesterFn, defaultOptionsHandler, formatQuery, presetResourceArguments };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,9 @@ type DefaultResourceOptions = {
11
11
  headers: {
12
12
  [header: string]: string;
13
13
  };
14
+ authHeaders: {
15
+ [authHeader: string]: () => Promise<string>;
16
+ };
14
17
  url: string;
15
18
  rejectUnauthorized: boolean;
16
19
  };
@@ -57,14 +60,15 @@ interface RootResourceOptions<C> {
57
60
  profileToken?: string;
58
61
  profileMode?: 'execution' | 'memory';
59
62
  }
63
+ type GitlabToken = string | (() => Promise<string>);
60
64
  interface BaseRequestOptionsWithOAuthToken<C> extends RootResourceOptions<C> {
61
- oauthToken: string;
65
+ oauthToken: GitlabToken;
62
66
  }
63
67
  interface BaseRequestOptionsWithAccessToken<C> extends RootResourceOptions<C> {
64
- token: string;
68
+ token: GitlabToken;
65
69
  }
66
70
  interface BaseRequestOptionsWithJobToken<C> extends RootResourceOptions<C> {
67
- jobToken: string;
71
+ jobToken: GitlabToken;
68
72
  }
69
73
  type BaseResourceOptions<C> = BaseRequestOptionsWithOAuthToken<C> | BaseRequestOptionsWithAccessToken<C> | BaseRequestOptionsWithJobToken<C>;
70
74
  declare class BaseResource<C extends boolean = false> {
@@ -74,9 +78,12 @@ declare class BaseResource<C extends boolean = false> {
74
78
  readonly headers: {
75
79
  [header: string]: string;
76
80
  };
81
+ readonly authHeaders: {
82
+ [authHeader: string]: () => Promise<string>;
83
+ };
77
84
  readonly camelize: C | undefined;
78
85
  readonly rejectUnauthorized: boolean;
79
86
  constructor({ sudo, profileToken, camelize, requesterFn, profileMode, host, prefixUrl, rejectUnauthorized, queryTimeout, ...tokens }: BaseResourceOptions<C>);
80
87
  }
81
88
 
82
- export { BaseRequestOptionsWithAccessToken, BaseRequestOptionsWithJobToken, BaseRequestOptionsWithOAuthToken, BaseResource, BaseResourceOptions, Constructable, DefaultRequestOptions, DefaultResourceOptions, FormattedResponse, OptionsHandlerFn, RequestHandlerFn, RequestOptions, RequesterType, ResponseBodyTypes, RootResourceOptions, createRequesterFn, defaultOptionsHandler, formatQuery, presetResourceArguments };
89
+ export { BaseRequestOptionsWithAccessToken, BaseRequestOptionsWithJobToken, BaseRequestOptionsWithOAuthToken, BaseResource, BaseResourceOptions, Constructable, DefaultRequestOptions, DefaultResourceOptions, FormattedResponse, GitlabToken, OptionsHandlerFn, RequestHandlerFn, RequestOptions, RequesterType, ResponseBodyTypes, RootResourceOptions, createRequesterFn, defaultOptionsHandler, formatQuery, presetResourceArguments };
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ function formatQuery(params = {}) {
11
11
  function isFormData(object) {
12
12
  return typeof object === "object" && object.constructor.name === "FormData";
13
13
  }
14
- function defaultOptionsHandler(resourceOptions, {
14
+ async function defaultOptionsHandler(resourceOptions, {
15
15
  body,
16
16
  searchParams,
17
17
  sudo,
@@ -19,7 +19,7 @@ function defaultOptionsHandler(resourceOptions, {
19
19
  asStream = false,
20
20
  method = "get"
21
21
  } = {}) {
22
- const { headers: preconfiguredHeaders, url } = resourceOptions;
22
+ const { headers: preconfiguredHeaders, authHeaders, url } = resourceOptions;
23
23
  const headers = { ...preconfiguredHeaders };
24
24
  const defaultOptions = {
25
25
  headers,
@@ -35,9 +35,11 @@ function defaultOptionsHandler(resourceOptions, {
35
35
  defaultOptions.body = body;
36
36
  } else {
37
37
  defaultOptions.body = JSON.stringify(xcase.decamelizeKeys(body));
38
- headers["content-type"] = "application/json";
38
+ defaultOptions.headers["content-type"] = "application/json";
39
39
  }
40
40
  }
41
+ const [authHeaderKey, authHeaderFn] = Object.entries(authHeaders)[0];
42
+ defaultOptions.headers[authHeaderKey] = await authHeaderFn();
41
43
  const q = formatQuery(searchParams);
42
44
  if (q)
43
45
  defaultOptions.searchParams = q;
@@ -73,11 +75,15 @@ function presetResourceArguments(resources, customConfig = {}) {
73
75
  }
74
76
 
75
77
  // src/BaseResource.ts
78
+ function getDynamicToken(tokenArgument) {
79
+ return tokenArgument instanceof Function ? tokenArgument() : Promise.resolve(tokenArgument);
80
+ }
76
81
  var BaseResource = class {
77
82
  url;
78
83
  requester;
79
84
  queryTimeout;
80
85
  headers;
86
+ authHeaders;
81
87
  camelize;
82
88
  rejectUnauthorized;
83
89
  constructor({
@@ -96,15 +102,19 @@ var BaseResource = class {
96
102
  throw new ReferenceError("requesterFn must be passed");
97
103
  this.url = [host, "api", "v4", prefixUrl].join("/");
98
104
  this.headers = {};
105
+ this.authHeaders = {};
99
106
  this.rejectUnauthorized = rejectUnauthorized;
100
107
  this.camelize = camelize;
101
108
  this.queryTimeout = queryTimeout;
102
109
  if ("oauthToken" in tokens)
103
- this.headers.authorization = `Bearer ${tokens.oauthToken}`;
110
+ this.authHeaders.authorization = async () => {
111
+ const token = await getDynamicToken(tokens.oauthToken);
112
+ return `Bearer ${token}`;
113
+ };
104
114
  else if ("jobToken" in tokens)
105
- this.headers["job-token"] = tokens.jobToken;
115
+ this.authHeaders["job-token"] = async () => getDynamicToken(tokens.jobToken);
106
116
  else if ("token" in tokens)
107
- this.headers["private-token"] = tokens.token;
117
+ this.authHeaders["private-token"] = async () => getDynamicToken(tokens.token);
108
118
  else {
109
119
  throw new ReferenceError("A token, oauthToken or jobToken must be passed");
110
120
  }
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ function formatQuery(params = {}) {
9
9
  function isFormData(object) {
10
10
  return typeof object === "object" && object.constructor.name === "FormData";
11
11
  }
12
- function defaultOptionsHandler(resourceOptions, {
12
+ async function defaultOptionsHandler(resourceOptions, {
13
13
  body,
14
14
  searchParams,
15
15
  sudo,
@@ -17,7 +17,7 @@ function defaultOptionsHandler(resourceOptions, {
17
17
  asStream = false,
18
18
  method = "get"
19
19
  } = {}) {
20
- const { headers: preconfiguredHeaders, url } = resourceOptions;
20
+ const { headers: preconfiguredHeaders, authHeaders, url } = resourceOptions;
21
21
  const headers = { ...preconfiguredHeaders };
22
22
  const defaultOptions = {
23
23
  headers,
@@ -33,9 +33,11 @@ function defaultOptionsHandler(resourceOptions, {
33
33
  defaultOptions.body = body;
34
34
  } else {
35
35
  defaultOptions.body = JSON.stringify(decamelizeKeys(body));
36
- headers["content-type"] = "application/json";
36
+ defaultOptions.headers["content-type"] = "application/json";
37
37
  }
38
38
  }
39
+ const [authHeaderKey, authHeaderFn] = Object.entries(authHeaders)[0];
40
+ defaultOptions.headers[authHeaderKey] = await authHeaderFn();
39
41
  const q = formatQuery(searchParams);
40
42
  if (q)
41
43
  defaultOptions.searchParams = q;
@@ -71,11 +73,15 @@ function presetResourceArguments(resources, customConfig = {}) {
71
73
  }
72
74
 
73
75
  // src/BaseResource.ts
76
+ function getDynamicToken(tokenArgument) {
77
+ return tokenArgument instanceof Function ? tokenArgument() : Promise.resolve(tokenArgument);
78
+ }
74
79
  var BaseResource = class {
75
80
  url;
76
81
  requester;
77
82
  queryTimeout;
78
83
  headers;
84
+ authHeaders;
79
85
  camelize;
80
86
  rejectUnauthorized;
81
87
  constructor({
@@ -94,15 +100,19 @@ var BaseResource = class {
94
100
  throw new ReferenceError("requesterFn must be passed");
95
101
  this.url = [host, "api", "v4", prefixUrl].join("/");
96
102
  this.headers = {};
103
+ this.authHeaders = {};
97
104
  this.rejectUnauthorized = rejectUnauthorized;
98
105
  this.camelize = camelize;
99
106
  this.queryTimeout = queryTimeout;
100
107
  if ("oauthToken" in tokens)
101
- this.headers.authorization = `Bearer ${tokens.oauthToken}`;
108
+ this.authHeaders.authorization = async () => {
109
+ const token = await getDynamicToken(tokens.oauthToken);
110
+ return `Bearer ${token}`;
111
+ };
102
112
  else if ("jobToken" in tokens)
103
- this.headers["job-token"] = tokens.jobToken;
113
+ this.authHeaders["job-token"] = async () => getDynamicToken(tokens.jobToken);
104
114
  else if ("token" in tokens)
105
- this.headers["private-token"] = tokens.token;
115
+ this.authHeaders["private-token"] = async () => getDynamicToken(tokens.token);
106
116
  else {
107
117
  throw new ReferenceError("A token, oauthToken or jobToken must be passed");
108
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitbeaker/requester-utils",
3
- "version": "39.1.1",
3
+ "version": "39.3.0",
4
4
  "description": "Utility functions for requester implementatons used in @gitbeaker",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -51,13 +51,13 @@
51
51
  "release": "auto shipit"
52
52
  },
53
53
  "dependencies": {
54
- "qs": "^6.11.1",
54
+ "qs": "^6.11.2",
55
55
  "xcase": "^2.0.1"
56
56
  },
57
57
  "devDependencies": {
58
- "@types/node": "^20.0.0",
59
- "tsup": "^6.7.0",
60
- "typescript": "^5.0.4"
58
+ "@types/node": "^20.3.1",
59
+ "tsup": "^7.1.0",
60
+ "typescript": "^5.1.3"
61
61
  },
62
- "gitHead": "cad136a360a24c553c59662aacc321f44fd53d64"
62
+ "gitHead": "39f6206dc562a762569da6570cc2a1586ab11f62"
63
63
  }