Skip to content

Commit

Permalink
Backend class improved
Browse files Browse the repository at this point in the history
  • Loading branch information
lambou committed Oct 1, 2020
1 parent 3bdd896 commit 91145eb
Showing 1 changed file with 98 additions and 54 deletions.
152 changes: 98 additions & 54 deletions src/helpers/Backend.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,110 @@
import { Obj } from '@noreajs/common'
import axios, {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
AxiosError,
} from "axios";
import Axios from "axios";
import IError from "../interfaces/IError";
AxiosError
} from 'axios'
import Axios from 'axios'
import IError from '../interfaces/IError'

export type ErrorMessageExtractorFuncType<T = any> = (
error?: T
) => string | Array<string> | undefined

export declare type BackendCallFuncProps<
ResponseType = any,
ErrorDataType = any
> = {
config: AxiosRequestConfig;
config: AxiosRequestConfig
errorConfig?: {
errorName: string;
errors: IError[];
udateErrors: (errors: IError[]) => void | Promise<void>;
reloadPageOnRefresh?: boolean;
};
errorMessageExtractor?: (
error?: ErrorDataType
) => string | Array<string> | undefined;
beforeStart?: () => Promise<void> | void;
errorName: string
errors: IError[]
udateErrors: (errors: IError[]) => void | Promise<void>
reloadPageOnRefresh?: boolean
}
errorMessageExtractor?: ErrorMessageExtractorFuncType<ErrorDataType>
beforeStart?: () => Promise<void> | void
successCallback?: (
response: AxiosResponse<ResponseType>
) => Promise<void> | void | ResponseType | Promise<ResponseType>;
) => Promise<void> | void | ResponseType | Promise<ResponseType>
errorCallback?: (
error: AxiosError<ErrorDataType>,
errorMessage?: string | Array<string>
) => Promise<void> | void | ErrorDataType | Promise<ErrorDataType>;
finishCallback?: () => Promise<void> | void;
};
) => Promise<void> | void | ErrorDataType | Promise<ErrorDataType>
finishCallback?: () => Promise<void> | void
}

export default class Backend {
BASE_URL: string = `${process.env.REACT_APP_BACKEND_BASE_URL}`;
private static instance: Backend;
private axiosInstance: AxiosInstance;
BASE_URL: string = `${process.env.BACKEND_BASE_URL}`
private static instance: Backend
private static config: AxiosRequestConfig
private static errorMessageExtractor?: ErrorMessageExtractorFuncType
private axiosInstance: AxiosInstance

private constructor(token?: string) {
const headers: any = {};
private constructor(config?: AxiosRequestConfig) {
// merge config
Backend.config = Obj.merge(config ?? {}, Backend.config ?? {})

if (token) {
headers.Authorization = `Token ${token}`;
}
// set base url
this.BASE_URL = `${Backend.config.baseURL}`

this.axiosInstance = axios.create({
baseURL: this.BASE_URL,
headers: headers,
});
// init instance
this.axiosInstance = axios.create(Backend.config)
}

static updateToken(value?: string) {
Backend.instance = new Backend(value);
/**
* Config backend default config
* @param options options
*/
static init(options: {
config?: AxiosRequestConfig
errorMessageExtractor?: ErrorMessageExtractorFuncType
}) {
Backend.errorMessageExtractor = options.errorMessageExtractor
Backend.config = options.config ?? Backend.config
}

static getInstance() {
return Backend.instance ?? new Backend();
/**
* Update axios request global headers
* @param headers new headers
*/
static updateHeaders(headers: any, merge = true) {
// expode config
const { headers: configHeaders, ...rest } = Backend.config

// update instance
Backend.instance = new Backend({
...rest,
headers: merge ? Obj.merge(headers, configHeaders) : headers
})
}

/**
* Get backend instance
* @param config axios request config
*/
static getInstance(config?: AxiosRequestConfig) {
return Backend.instance ?? new Backend(config)
}

/**
* Get axios instance
*/
axios() {
return this.axiosInstance;
return this.axiosInstance
}

/**
* Make a backend call
* @param params call options
*/
async call<ResponseType = any, ErrorDataType = any>(
params: BackendCallFuncProps<ResponseType, ErrorDataType>
) {
// before start
if (params.beforeStart) {
params.beforeStart();
params.beforeStart()
}

// make request
Expand All @@ -80,27 +117,34 @@ export default class Backend {
params.errorConfig.errors.filter(
(item) => item.name !== (params.errorConfig?.errorName as any)
)
);
)
}

// success callback
if (params.successCallback) {
const r = await params.successCallback(response);
return r ?? response.data;
const r = await params.successCallback(response)
return r ?? response.data
} else {
return response.data;
return response.data
}
})
.catch(async (error: AxiosError<ErrorDataType>) => {
// only uncancelled error are traited
if (!Axios.isCancel(error)) {
let errorMessage =
(error.response?.data as any)?.message ??
(error.response?.data as any)?.Message;
(error.response?.data as any)?.Message

// use extractor if defined
if (!errorMessage && params.errorMessageExtractor) {
errorMessage = params.errorMessageExtractor(error.response?.data);
if (!errorMessage) {
// local extractor
if (params.errorMessageExtractor) {
errorMessage = params.errorMessageExtractor(error.response?.data)
}
// global extractor
else if (Backend.errorMessageExtractor) {
errorMessage = Backend.errorMessageExtractor(error.response?.data)
}
}

if (
Expand All @@ -112,31 +156,31 @@ export default class Backend {
// push error
params.errorConfig.errors.push({
name: params.errorConfig.errorName as any,
type: "HTTP",
type: 'HTTP',
httpError: error,
message: errorMessage,
refreshCallback: () => {
this.call(params);
this.call(params)
},
reloadPage: params.errorConfig.reloadPageOnRefresh,
});
reloadPage: params.errorConfig.reloadPageOnRefresh
})
}

if (params.errorCallback) {
const r = await params.errorCallback(error, errorMessage);
return r === undefined ? error.response?.data : r;
const r = await params.errorCallback(error, errorMessage)
return r === undefined ? error.response?.data : r
} else {
return error.response?.data;
return error.response?.data
}
}else{
return error.response?.data;
} else {
return error.response?.data
}
})
.finally(() => {
// finish callback
if (params.finishCallback) {
params.finishCallback();
params.finishCallback()
}
});
})
}
}

0 comments on commit 91145eb

Please sign in to comment.