import type http from 'http'; import { Readable } from 'stream'; import type Logger from 'bunyan'; import { ApiConfig } from './types/ApiConfig'; import { AuthOptions } from './types/AuthOptions'; import { Call, Request, RequestWithBody, StreamRequest } from './types/Request'; import { AuthenticationClient } from './types/AuthenticationClient'; import { SanitisedError } from './types/Errors'; /** * Base class for REST API clients. */ export default class RestClient { protected readonly name: string; protected readonly config: ApiConfig; protected readonly logger: Logger | Console; private readonly authenticationClient?; private readonly agent; /** * Creates an instance of RestClient. * * @param name - The name of the API client. * @param config - The API configuration, including URL, timeout, and agent options. * @param logger - A logger instance for logging. * @param authenticationClient - (Optional) The client responsible for retrieving system authentication tokens. */ constructor(name: string, config: ApiConfig, logger: Logger | Console, authenticationClient?: AuthenticationClient | undefined); /** * Creates a keepalive agent based on the API configuration. If the API URL starts with 'https', an HttpsAgent is created; otherwise, an HttpAgent is used. * Proxy information will be read from the environment if present. * * protected to allow clients to override to provide their own agent inst * * @param config * @returns a http agent */ protected createAgent(config: ApiConfig): http.Agent; /** * Retrieves the base API URL. * * @returns The base API URL. */ private apiUrl; /** * Retrieves the timeout configuration. * * @returns The timeout configuration. */ private timeoutConfig; /** * Provides a default mechanism for handling errors * @param path - path of current request * @param method - verb of HTTP request * @param error - the sanitised error * * @returns an optional custom response * @throws an optional error */ protected handleError(path: string, method: string, error: SanitisedError): Response; /** * Provides a default mechanism for logging errors * @param path - path of current request * @param method - verb of HTTP request * @param error - the sanitised error */ protected logError(path: string, method: string, error: SanitisedError): void; private readonly ERROR_CODES; private readonly STATUS_CODES; /** * Returns a retry handler function. * * @param retry - Indicates whether to retry the request. * @returns A function that handles retries. */ private handleRetry; /** * Sends a GET request to the API. * * @param request - The request options including path, query, headers, responseType, and raw flag. * @param authOptions - (Optional) Either an AuthOptions object, a raw JWT string, or undefined for no auth. * @returns The response body or the full response if raw is true. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ get({ path, query, headers, responseType, raw, retries, timeout, errorHandler, retryHandler, }: Request, authOptions?: AuthOptions | string): Promise; /** * Sends a request with a body (PATCH, POST, or PUT) to the API. * * @param method - The HTTP method ('patch', 'post', or 'put'). * @param request - The request options including path, query, headers, responseType, data, raw flag, and retry flag. * @param authOptions - (Optional) Either an AuthOptions object, a raw JWT string, or undefined for no auth. * @returns The response body or the full response if raw is true. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ private requestWithBody; /** * Sends a PATCH request to the API. * * @param request - The PATCH request options. * @param authOptions - The authentication options. * @returns The response body. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ patch(request: RequestWithBody, authOptions?: AuthOptions | string): Promise; /** * Sends a POST request to the API. * * @param request - The POST request options. * @param authOptions - The authentication options. * @returns The response body. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ post(request: RequestWithBody, authOptions?: AuthOptions | string): Promise; /** * Sends a PUT request to the API. * * @param request - The PUT request options. * @param authOptions - The authentication options. * @returns The response body. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ put(request: RequestWithBody, authOptions?: AuthOptions | string): Promise; /** * Sends a DELETE request to the API. * * @param request - The DELETE request options including path, query, headers, responseType, and raw flag. * @param authOptions - (Optional) Either an AuthOptions object, a raw JWT string, or undefined for no auth. * @returns The response body. * @throws {SanitisedError} if the request fails. Note that this is the default behaviour, but can be * changed to a different type by specifying a custom errorHandler. */ delete({ path, query, headers, responseType, raw, retries, timeout, errorHandler, retryHandler, }: Request, authOptions?: AuthOptions | string): Promise; /** * Streams data from the API. * * @param request - The stream request options including path and headers. * @param authOptions - (Optional) Either an AuthOptions object, a raw JWT string, or undefined for no auth. * @returns A Readable stream containing the response data. If this request fails then the promise is rejected with * type SanitisedError. */ stream({ path, headers, errorLogger, timeout }: StreamRequest, authOptions?: AuthOptions | string): Promise; /** * Make a request using underlying superagent instance, potentially getting a token. * * In an ideal world, this would rarely be used but provides an escape hatch to cater for bespoke usecases. * * @param call - A callback that provides the client a token and the underlying superagent instance. * @param authOptions - The authentication options for this call. * @returns The response body. */ makeRestClientCall(authOptions: AuthOptions | string, call: Call): Promise; /** * Resolves an authentication token from several possible inputs: * 1) A raw JWT string * 2) An AuthOptions object referencing a system or user token * 3) Undefined (no token) * * @param authOptions - AuthOptions, a raw token string, or undefined (no auth). * @returns A promise that resolves to the authentication token or undefined if no auth. * @throws An error if no user token is provided for user-token calls. * @throws An error if no authentication client is provided for system token calls. */ private resolveToken; }