101 lines
2.2 KiB
TypeScript
101 lines
2.2 KiB
TypeScript
export interface UmamiApiErrorBody {
|
|
error?: {
|
|
message?: string;
|
|
code?: string;
|
|
status?: number;
|
|
[key: string]: unknown;
|
|
};
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
/**
|
|
* Thrown for any non-2xx response. `code` mirrors the API's error code
|
|
* (`unauthorized`, `forbidden`, `not-found`, `bad-request`, `server-error`, …).
|
|
*/
|
|
export class UmamiApiError extends Error {
|
|
readonly status: number;
|
|
readonly code: string;
|
|
readonly method: string;
|
|
readonly url: string;
|
|
readonly body: unknown;
|
|
|
|
constructor(options: {
|
|
status: number;
|
|
code?: string;
|
|
message?: string;
|
|
method: string;
|
|
url: string;
|
|
body?: unknown;
|
|
}) {
|
|
super(options.message ?? defaultMessage(options.status));
|
|
this.name = 'UmamiApiError';
|
|
this.status = options.status;
|
|
this.code = options.code ?? defaultCode(options.status);
|
|
this.method = options.method;
|
|
this.url = options.url;
|
|
this.body = options.body;
|
|
}
|
|
|
|
get isUnauthorized() {
|
|
return this.status === 401;
|
|
}
|
|
|
|
get isForbidden() {
|
|
return this.status === 403;
|
|
}
|
|
|
|
get isNotFound() {
|
|
return this.status === 404;
|
|
}
|
|
|
|
get isRateLimited() {
|
|
return this.status === 429;
|
|
}
|
|
|
|
get isServerError() {
|
|
return this.status >= 500;
|
|
}
|
|
}
|
|
|
|
export function isUmamiApiError(error: unknown): error is UmamiApiError {
|
|
return error instanceof UmamiApiError || (error as { name?: string })?.name === 'UmamiApiError';
|
|
}
|
|
|
|
function defaultCode(status: number) {
|
|
switch (status) {
|
|
case 400:
|
|
return 'bad-request';
|
|
case 401:
|
|
return 'unauthorized';
|
|
case 403:
|
|
return 'forbidden';
|
|
case 404:
|
|
return 'not-found';
|
|
case 413:
|
|
return 'payload-too-large';
|
|
case 429:
|
|
return 'rate-limited';
|
|
case 503:
|
|
return 'service-unavailable';
|
|
default:
|
|
return status >= 500 ? 'server-error' : 'request-failed';
|
|
}
|
|
}
|
|
|
|
function defaultMessage(status: number) {
|
|
switch (status) {
|
|
case 400:
|
|
return 'Bad request';
|
|
case 401:
|
|
return 'Unauthorized';
|
|
case 403:
|
|
return 'Forbidden';
|
|
case 404:
|
|
return 'Not found';
|
|
case 429:
|
|
return 'Too many requests';
|
|
default:
|
|
return status >= 500 ? 'Server error' : `Request failed with status ${status}`;
|
|
}
|
|
}
|