import { SerializationStyle, serializePath, serializeQuery } from './serializer'; import { HttpMethod, HttpRequest, HttpResponse, Options, RetryOptions, SdkConfig } from './types'; import { RequestHandlerChain } from './handlers/handler-chain'; import { HookHandler } from './handlers/hook-handler'; import { ResponseValidationHandler } from './handlers/response-validation-handler'; import { RequestValidationHandler } from './handlers/request-validation-handler'; import { CustomHook } from './hooks/custom-hook'; import { TerminatingHandler } from './handlers/terminating-handler'; import { RetryHandler } from './handlers/retry-handler'; export class HttpClient { private readonly requestHandlerChain = new RequestHandlerChain(); constructor( private config: SdkConfig, hook = new CustomHook(), ) { this.requestHandlerChain.addHandler(new ResponseValidationHandler()); this.requestHandlerChain.addHandler(new RequestValidationHandler()); this.requestHandlerChain.addHandler(new RetryHandler()); this.requestHandlerChain.addHandler(new HookHandler(hook)); this.requestHandlerChain.addHandler(new TerminatingHandler()); } get(url: string, options: Options): Promise> { const request = this.constructRequest(url, 'GET', options); return this.performRequest(request); } async post(url: string, options: Options): Promise> { const request = this.constructRequest(url, 'POST', options); return this.performRequest(request); } async put(url: string, options: Options): Promise> { const request = this.constructRequest(url, 'PUT', options); return this.performRequest(request); } async patch(url: string, options: Options): Promise> { const request = this.constructRequest(url, 'PATCH', options); return this.performRequest(request); } async delete(url: string, options: Options): Promise> { const request = this.constructRequest(url, 'DELETE', options); return this.performRequest(request); } buildPath( pathPattern: string, pathArguments: Record, style = SerializationStyle.SIMPLE, explode = false, ): string { return serializePath(pathPattern, pathArguments, style, explode); } setBaseUrl(url: string): void { this.config.baseUrl = url; } setConfig(config: SdkConfig): void { this.config = config; } private async performRequest(request: HttpRequest): Promise> { return this.requestHandlerChain.callChain(request); } private constructRequest( relativeUrl: string, method: HttpMethod, options: Options, ): HttpRequest { const url = this.constructUrl(relativeUrl, options); return { method, url, config: this.config, ...options, retry: this.constructRetry(options), }; } private constructUrl(url: string, options?: Options): string { const queryParameters = serializeQuery(options?.queryParams); return `${this.config.baseUrl}${url}${queryParameters}`; } private constructRetry({ retry }: Options): Required { return { attempts: retry?.attempts ?? 3, delayMs: retry?.delayMs ?? 150, }; } }