It seems like you're heading in the right direction.
One effective approach is to abstract the axios client just as you would with any other http client and conceal the axios implementation.
To achieve this, consider creating a separate class for that purpose.
export class HttpClient extends HttpMethods {
_http: AxiosInstance;
constructor() {
super();
this._http = axios.create({
...this._options,
validateStatus: status => status >= 200 && status < 400,
});
}
setAdditionalHeaders(headers: object, override?: boolean): void {
this._options = _.merge({}, override ? {} : this._options, { headers });
}
public async get<T>(path: string, params?: any, headers?: object): Promise<Result<T>> {
if (headers) {
this.setAdditionalHeaders(headers, true);
}
const result = await this._http({
method: 'GET',
url: path,
params,
headers: this._options,
...this.hydrateConfig(this._config),
});
return result;
}
}
export abstract class HttpMethods {
public _http: any;
protected _options: object;
public abstract get<T>(path: string, params?: any, headers?: object): Promise<Result<T>>;
}
You can then explore chainable functions where your class, which conceals the use of axios, is injected into the process.
export function httpBuilder<I extends HttpMethods>(client: I): IHttpBuilder {
return {
...httpRequestMethods(client),
};
}
function httpRequestMethods(instance: HttpMethods): BuilderMethod {
const { config } = instance;
return {
get<T>(path: string, params?: any, headers?: object): ChainableHttp & HttpExecutableCommand<T> {
return {
...executableCommand<T>(path, instance, 'GET', requests, null, params, headers),
};
},
}
function executableCommand<T>(
path: string,
instance: HttpMethods,
commandType: CommandType,
requests: RequestType[],
data?: any,
params?: any,
headers?: object,
): HttpExecutableCommand<T> {
return {
async execute(): Promise<Result<T>> {
const result = await getResolvedResponse<T>(path, instance, commandType, data, params, headers);
return result;
},
};
}
async function getResolvedResponse<T>(
path: string,
instance: HttpMethods,
commandType: CommandType,
data?: any,
params?: any,
headers?: object,
): Promise<Result<T>> {
let result: Result<T>;
if (commandType === 'GET') {
result = await instance.get<T>(path, params, headers);
}
return result;
}
This example serves as a guide to enhancing functionalities of your http client, whether it be axios, fetch, or any other choice you prefer :-)