I think you're on the good way.
The best thing you can do is to abstract axios client as you would do with another http client and hide axios implementation.
For this, you can make a class for instead
export class HttpClient extends HttpMethods {
_http: AxiosInstance;
constructor() {
super();
this._http = axios.create({
...this._options,
validateStatus: status => status >= 200 && status < 400,
});
}
setAdditionnalHeaders(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.setAdditionnalHeaders(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>>;
}
And then play with chainable functions where you will inject your class which hide that axios is use in this.
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 is an example for help if you want to perform extra feature on your http client whether is axios, fetch or whatever you want :-)