47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
declare global {
|
|
interface Error {
|
|
/* Extra fields on errors are extremely helpful for debugging. */
|
|
[metadata: string]: unknown;
|
|
}
|
|
}
|
|
|
|
/** Retrieve an error message from any value */
|
|
export function message(error: unknown): string {
|
|
const message = (error as { message: unknown })?.message ?? error;
|
|
try {
|
|
return typeof message === "string" ? message : JSON.stringify(message);
|
|
} catch {}
|
|
try {
|
|
return String(message);
|
|
} catch {}
|
|
return `Could not stringify error message ${typeof message}`;
|
|
}
|
|
|
|
/** Retrieve an error-like object from any value. Useful to check fields. */
|
|
export function obj(error: unknown): { message: string } & Partial<Error> {
|
|
if (error instanceof Error) return error;
|
|
return {
|
|
message: message(error),
|
|
...(typeof error === "object" && error),
|
|
};
|
|
}
|
|
|
|
/* Node.js error codes are strings */
|
|
export function code(error: unknown): NodeErrorCode | null {
|
|
const code = (error as { code: unknown })?.code;
|
|
return typeof code === "string" ? code : null;
|
|
}
|
|
|
|
/** Attach extra fields and throw */
|
|
export function rethrowWithMetadata(
|
|
err: unknown,
|
|
meta: Record<string, unknown>,
|
|
): never {
|
|
const error = err && typeof err === "object" ? err : new Error(message(err)); // no stack trace :/
|
|
Object.assign(error, meta);
|
|
throw error;
|
|
}
|
|
|
|
export type NodeErrorCode =
|
|
| keyof typeof import("node:os").constants.errno
|
|
| (string & {});
|