114 lines
2.6 KiB
TypeScript
114 lines
2.6 KiB
TypeScript
import { AxiosError } from "axios";
|
|
import _ from "lodash";
|
|
import { DTOModel, isDTO } from "./dto_model";
|
|
|
|
export interface FailureI {
|
|
status?: number;
|
|
message: string;
|
|
key?: string;
|
|
meta?: FailureMeta;
|
|
}
|
|
|
|
interface FailureMeta {
|
|
isRequestFailure?: boolean;
|
|
isNetworkFailure?: boolean;
|
|
isPlainFailure?: boolean;
|
|
data?: any;
|
|
[prop: string]: any | undefined;
|
|
}
|
|
|
|
class Failure implements FailureI {
|
|
message: string;
|
|
key?: string | undefined;
|
|
status?: number | undefined;
|
|
meta?: FailureMeta;
|
|
static isf = true;
|
|
|
|
/**
|
|
*
|
|
* @param {Failure} o
|
|
* @returns {boolean}
|
|
*/
|
|
static isFailure(o: any): o is Failure {
|
|
if (!_.isObjectLike(o)) return false;
|
|
if (_.has(o, "message")) return true;
|
|
return false;
|
|
}
|
|
|
|
constructor({ status, message, key, meta }: FailureI) {
|
|
this.status = status;
|
|
this.message = message;
|
|
this.key = key;
|
|
this.meta = meta;
|
|
console.error([key ?? "", message].filter((i) => i.length !== 0).join(":"));
|
|
}
|
|
|
|
static fromReason(reason: AxiosError<any, any>, key?: string): Failure {
|
|
|
|
try {
|
|
if(!Failure.verifyContainsDTO(reason)) {
|
|
throw reason;
|
|
}
|
|
if (reason.response) {
|
|
return new Failure({
|
|
status: reason.response!.status,
|
|
message:
|
|
reason.response!.data.message ?? "Unknown response error model",
|
|
key: key,
|
|
meta: {
|
|
isRequestFailure: true,
|
|
data: reason.response.data,
|
|
},
|
|
});
|
|
}
|
|
if (reason.request) {
|
|
return new Failure({
|
|
message: `Something went wrong while ${reason.config.url} had been called`,
|
|
key: `unreachedResponse(${key})`,
|
|
meta: {
|
|
isNetworkFailure: true,
|
|
},
|
|
});
|
|
}
|
|
throw reason;
|
|
} catch (error) {
|
|
return new Failure({
|
|
message: reason.message,
|
|
key: key,
|
|
meta: { isPlainFailure: true },
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verifies that passed object matches [DTOModel] structure
|
|
*
|
|
* Otherwise it will rethrow passed object
|
|
*/
|
|
static verifyContainsDTO(
|
|
reason: AxiosError<any, any>
|
|
): reason is AxiosError<DTOModel<any>, any> {
|
|
return [reason.response, reason.request].reduce((acc, obj) => {
|
|
if (acc || isDTO(obj)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}, false);
|
|
}
|
|
|
|
toString(): string {
|
|
return `${this.message} (${this.key ?? "key unknown"}) ${
|
|
this.status ?? "status unknown"
|
|
}`;
|
|
}
|
|
|
|
mapKeyWith(transpiler: (key: string) => string) {
|
|
if (!this.key) {
|
|
return this.message;
|
|
}
|
|
return transpiler(this.key);
|
|
}
|
|
}
|
|
|
|
export default Failure;
|