-
Notifications
You must be signed in to change notification settings - Fork 990
/
Copy patherror.ts
128 lines (115 loc) · 3.48 KB
/
error.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { defaultTo } from "lodash";
interface FirebaseErrorOptions {
children?: unknown[];
context?: unknown;
exit?: number;
original?: Error;
status?: number;
}
const DEFAULT_CHILDREN: NonNullable<FirebaseErrorOptions["children"]> = [];
const DEFAULT_EXIT: NonNullable<FirebaseErrorOptions["exit"]> = 1;
const DEFAULT_STATUS: NonNullable<FirebaseErrorOptions["status"]> = 500;
export class FirebaseError extends Error {
readonly children: unknown[];
readonly context: unknown | undefined;
readonly exit: number;
readonly message: string;
readonly name = "FirebaseError";
readonly original: Error | undefined;
readonly status: number;
constructor(message: string, options: FirebaseErrorOptions = {}) {
super();
this.children = defaultTo(options.children, DEFAULT_CHILDREN);
this.context = options.context;
this.exit = defaultTo(options.exit, DEFAULT_EXIT);
this.message = message;
this.original = options.original;
this.status = defaultTo(options.status, DEFAULT_STATUS);
}
}
/**
* Safely gets an error message from an unknown object
* @param err an unknown error type
* @param defaultMsg an optional message to return if the err is not Error or string
* @return An error string
*/
export function getErrMsg(err: unknown, defaultMsg?: string): string {
if (err instanceof Error) {
return err.message;
} else if (typeof err === "string") {
return err;
} else if (defaultMsg) {
return defaultMsg;
}
return JSON.stringify(err);
}
/**
* Safely gets an error stack (or error message if no stack is available)
* from an unknown object
* @param err The potential error object
* @return a string representing the error stack or the error message.
*/
export function getErrStack(err: unknown): string {
if (err instanceof Error) {
return err.stack || err.message;
}
return getErrMsg(err);
}
/**
* A typeguard for objects
* @param value The value to check
*/
export function isObject(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
/**
* Safely gets a status from an unknown object if it has one.
* @param err The error to get the status of
* @param defaultStatus a default status if there is none
* @return the err status, a default status or DEFAULT_STATUS
*/
export function getErrStatus(err: unknown, defaultStatus?: number): number {
if (isObject(err) && err.status && typeof err.status === "number") {
return err.status;
}
return defaultStatus || DEFAULT_STATUS;
}
/**
* Safely gets an error object from an unknown object
* @param err The error to get an Error for.
* @return an Error object
*/
export function getError(err: unknown): Error {
if (err instanceof Error) {
return err;
}
return Error(getErrMsg(err));
}
/**
* Checks if a FirebaseError is caused by attempting something
* that requires billing enabled while billing is not enabled.
*/
export function isBillingError(e: {
context?: {
body?: {
error?: {
details?: {
type: string;
reason?: string;
violations?: { type: string }[];
}[];
};
};
};
}): boolean {
return !!e.context?.body?.error?.details?.find((d) => {
return (
d.violations?.find((v) => v.type === "serviceusage/billing-enabled") ||
d.reason === "UREQ_PROJECT_BILLING_NOT_FOUND"
);
});
}
/**
* Checks whether an unknown object (such as an error) has a message field
*/
export const hasMessage = (e: any): e is { message: string } => !!e?.message;