Unify Harbor error handling across server and client
All checks were successful
Build and Deploy Gateway / build-and-push (push) Successful in 15s
Build and Deploy Gateway / deploy (push) Successful in 12s

This commit is contained in:
2026-07-11 20:38:41 +03:00
parent 457dd912d1
commit 9da4fef1f0
16 changed files with 493 additions and 100 deletions

View File

@@ -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;
}