Unify Harbor error handling across server and client
This commit is contained in:
@@ -1,16 +1,51 @@
|
||||
async function request(url, options = {}) {
|
||||
const response = await fetch(url, {
|
||||
...options,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
...(options.headers || {}),
|
||||
},
|
||||
});
|
||||
const data = await response.json().catch(() => ({}));
|
||||
import { ERROR_DEFINITIONS, errorDefinition } from '../shared/errors.js';
|
||||
|
||||
export class HarborApiError extends Error {
|
||||
constructor(payload = {}, status = 0) {
|
||||
const code = ERROR_DEFINITIONS[payload.code] ? payload.code : 'UNKNOWN';
|
||||
const definition = errorDefinition(code);
|
||||
super(definition.message);
|
||||
this.name = 'HarborApiError';
|
||||
this.code = code;
|
||||
this.status = status >= 400 ? status : definition.status;
|
||||
this.retryable = definition.retryable;
|
||||
this.details = payload.details;
|
||||
this.correlationId = payload.correlationId
|
||||
|| globalThis.crypto?.randomUUID?.()
|
||||
|| new Date().toISOString();
|
||||
}
|
||||
}
|
||||
|
||||
export function validationStatusForError(error) {
|
||||
return error?.code === 'SUBSCRIPTION_INVALID' ? 'invalid' : 'unavailable';
|
||||
}
|
||||
|
||||
export async function request(url, options = {}, fetchImpl = fetch) {
|
||||
let response;
|
||||
try {
|
||||
response = await fetchImpl(url, {
|
||||
...options,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
...(options.headers || {}),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
if (error?.name === 'AbortError') throw error;
|
||||
throw new HarborApiError({ code: 'CONTROL_UNREACHABLE' });
|
||||
}
|
||||
|
||||
let data = {};
|
||||
try {
|
||||
data = await response.json();
|
||||
} catch {
|
||||
if (response.ok) throw new HarborApiError({ code: 'UNKNOWN' }, response.status);
|
||||
}
|
||||
if (!response.ok || data?.success === false) {
|
||||
const error = new Error(data?.error || `Запрос ${url} завершился ошибкой ${response.status}`);
|
||||
error.status = response.status;
|
||||
throw error;
|
||||
const payload = data?.error && typeof data.error === 'object'
|
||||
? data.error
|
||||
: { code: response.status >= 500 ? 'CONTROL_UNREACHABLE' : 'UNKNOWN' };
|
||||
throw new HarborApiError(payload, response.status);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user