Frontend/src/core/failure.ts

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;