mirror of
https://github.com/jdalrymple/gitbeaker.git
synced 2026-01-25 16:04:01 +00:00
104 lines
2.8 KiB
TypeScript
104 lines
2.8 KiB
TypeScript
import { Agent } from 'https';
|
|
import { decamelizeKeys } from 'xcase';
|
|
import { stringify } from 'query-string';
|
|
|
|
// Types
|
|
export interface RequesterType {
|
|
get(service: object, endpoint: string, options?: object): Promise<any>;
|
|
post(service: object, endpoint: string, options?: object): Promise<any>;
|
|
put(service: object, endpoint: string, options?: object): Promise<any>;
|
|
delete(service: object, endpoint: string, options?: object): Promise<any>;
|
|
stream?(service: object, endpoint: string, options?: object): Promise<any>;
|
|
}
|
|
|
|
export interface Service {
|
|
headers: Record<string, string | string[]>;
|
|
requestTimeout: number;
|
|
url: string;
|
|
rejectUnauthorized?: boolean;
|
|
}
|
|
|
|
export type DefaultRequestOptions = {
|
|
body?: FormData | object;
|
|
query?: object;
|
|
sudo?: string;
|
|
method?: string;
|
|
};
|
|
|
|
// Utility methods
|
|
export function formatQuery(options) {
|
|
return stringify(decamelizeKeys(options || {}) as object, { arrayFormat: 'bracket' });
|
|
}
|
|
|
|
export function defaultRequest(
|
|
service: Service,
|
|
{ body, query, sudo, method = 'get' }: DefaultRequestOptions = {},
|
|
): Record<string, string | number | FormData | Agent | Record<string, string | string[] | Agent>> {
|
|
const { headers } = service;
|
|
let agent;
|
|
let bod;
|
|
|
|
if (sudo) headers.sudo = sudo;
|
|
|
|
// FIXME: Not the best comparison, but...it will have to do for now.
|
|
if (typeof body === 'object' && body.constructor.name !== 'FormData') {
|
|
bod = JSON.stringify(decamelizeKeys(body));
|
|
headers['content-type'] = 'application/json';
|
|
} else {
|
|
bod = body;
|
|
}
|
|
|
|
return {
|
|
agent,
|
|
headers,
|
|
timeout: service.requestTimeout,
|
|
method,
|
|
searchParams: formatQuery(query),
|
|
prefixUrl: service.url,
|
|
body: bod,
|
|
};
|
|
}
|
|
|
|
export function createInstance(optionsHandler, requestHandler): RequesterType {
|
|
const requester: RequesterType = {} as RequesterType;
|
|
const methods = ['get', 'post', 'put', 'delete', 'stream'];
|
|
|
|
methods.forEach((m) => {
|
|
/* eslint func-names:0 */
|
|
requester[m] = function (service, endpoint, options) {
|
|
const requestOptions = optionsHandler(service, { ...options, method: m });
|
|
|
|
return requestHandler(endpoint, requestOptions);
|
|
};
|
|
});
|
|
|
|
return requester;
|
|
}
|
|
|
|
export interface Constructable<T = {}> {
|
|
new (...args: any[]): T;
|
|
}
|
|
|
|
function extendClass<T extends Constructable>(Base: T, customConfig: object): T {
|
|
return class extends Base {
|
|
constructor(...options: any[]) {
|
|
const [config, ...opts] = options;
|
|
|
|
super({ ...customConfig, ...config }, ...opts);
|
|
}
|
|
};
|
|
}
|
|
|
|
export function modifyServices<T extends { [name: string]: Constructable }>(
|
|
services: T,
|
|
customConfig: object = {},
|
|
) {
|
|
const updated: { [name: string]: Constructable } = {};
|
|
|
|
Object.entries(services).forEach(([k, s]) => {
|
|
updated[k] = extendClass(s, customConfig);
|
|
});
|
|
|
|
return updated as T;
|
|
}
|