2023-05-24 10:20:15 +02:00
|
|
|
/* eslint-disable max-classes-per-file */
|
2023-02-02 21:19:37 +01:00
|
|
|
// This is a subset of, and the counterpart to errors.go
|
|
|
|
|
|
|
|
const maybeToJson = async (response) => {
|
2023-05-23 21:13:01 +02:00
|
|
|
try {
|
|
|
|
return await response.json();
|
|
|
|
} catch (e) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
2023-02-02 21:19:37 +01:00
|
|
|
|
|
|
|
export class UnauthorizedError extends Error {
|
2023-05-23 21:13:01 +02:00
|
|
|
constructor() {
|
|
|
|
super("Unauthorized");
|
|
|
|
}
|
2023-02-02 21:19:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class UserExistsError extends Error {
|
2023-05-23 21:13:01 +02:00
|
|
|
static CODE = 40901; // errHTTPConflictUserExists
|
2023-05-24 09:03:28 +02:00
|
|
|
|
2023-05-23 21:13:01 +02:00
|
|
|
constructor() {
|
|
|
|
super("Username already exists");
|
|
|
|
}
|
2023-02-02 21:19:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class TopicReservedError extends Error {
|
2023-05-23 21:13:01 +02:00
|
|
|
static CODE = 40902; // errHTTPConflictTopicReserved
|
2023-05-24 09:03:28 +02:00
|
|
|
|
2023-05-23 21:13:01 +02:00
|
|
|
constructor() {
|
|
|
|
super("Topic already reserved");
|
|
|
|
}
|
2023-02-02 21:19:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class AccountCreateLimitReachedError extends Error {
|
2023-05-23 21:13:01 +02:00
|
|
|
static CODE = 42906; // errHTTPTooManyRequestsLimitAccountCreation
|
2023-05-24 09:03:28 +02:00
|
|
|
|
2023-05-23 21:13:01 +02:00
|
|
|
constructor() {
|
|
|
|
super("Account creation limit reached");
|
|
|
|
}
|
2023-02-02 21:19:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
export class IncorrectPasswordError extends Error {
|
2023-05-23 21:13:01 +02:00
|
|
|
static CODE = 40026; // errHTTPBadRequestIncorrectPasswordConfirmation
|
2023-05-24 09:03:28 +02:00
|
|
|
|
2023-05-23 21:13:01 +02:00
|
|
|
constructor() {
|
|
|
|
super("Password incorrect");
|
|
|
|
}
|
2023-02-02 21:19:37 +01:00
|
|
|
}
|
2023-05-24 10:20:15 +02:00
|
|
|
|
|
|
|
export const throwAppError = async (response) => {
|
|
|
|
if (response.status === 401 || response.status === 403) {
|
|
|
|
console.log(`[Error] HTTP ${response.status}`, response);
|
|
|
|
throw new UnauthorizedError();
|
|
|
|
}
|
|
|
|
const error = await maybeToJson(response);
|
|
|
|
if (error?.code) {
|
|
|
|
console.log(`[Error] HTTP ${response.status}, ntfy error ${error.code}: ${error.error || ""}`, response);
|
|
|
|
if (error.code === UserExistsError.CODE) {
|
|
|
|
throw new UserExistsError();
|
|
|
|
} else if (error.code === TopicReservedError.CODE) {
|
|
|
|
throw new TopicReservedError();
|
|
|
|
} else if (error.code === AccountCreateLimitReachedError.CODE) {
|
|
|
|
throw new AccountCreateLimitReachedError();
|
|
|
|
} else if (error.code === IncorrectPasswordError.CODE) {
|
|
|
|
throw new IncorrectPasswordError();
|
|
|
|
} else if (error?.error) {
|
|
|
|
throw new Error(`Error ${error.code}: ${error.error}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
console.log(`[Error] HTTP ${response.status}, not a ntfy error`, response);
|
|
|
|
throw new Error(`Unexpected response ${response.status}`);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const fetchOrThrow = async (url, options) => {
|
|
|
|
const response = await fetch(url, options);
|
|
|
|
if (response.status !== 200) {
|
|
|
|
await throwAppError(response);
|
|
|
|
}
|
|
|
|
return response; // Promise!
|
|
|
|
};
|