feat: enhance evobgp with new command-line tools for bundle management, including pull, verify, and apply functionalities. Update go.mod to include necessary dependencies and complete todos in architecture plan for improved observability and deployment practices.
CI / changes (push) Successful in 4s
CI / go (push) Failing after 6s
CI / bird2 (push) Has been skipped
CI / openapi (push) Has been skipped

This commit is contained in:
Denozordec
2026-04-05 14:07:45 +07:00
parent 272542b92a
commit bf52b21150
131 changed files with 9222 additions and 17 deletions
+47
View File
@@ -0,0 +1,47 @@
import { browser } from '$app/environment';
export const TOKEN_STORAGE_KEY = 'evobgp_api_token';
export type Problem = {
title?: string;
status?: number;
detail?: string;
};
function mergeHeaders(init?: RequestInit): Headers {
const h = new Headers(init?.headers);
if (!h.has('Accept')) {
h.set('Accept', 'application/json');
}
if (browser) {
const t = localStorage.getItem(TOKEN_STORAGE_KEY);
if (t && !h.has('Authorization')) {
h.set('Authorization', `Bearer ${t}`);
}
}
return h;
}
export async function apiFetch(path: string, init?: RequestInit): Promise<Response> {
if (!browser) {
throw new Error('API is only available in the browser');
}
return fetch(path, { ...init, headers: mergeHeaders(init) });
}
export async function apiJSON<T>(path: string, init?: RequestInit): Promise<T> {
const res = await apiFetch(path, init);
const text = await res.text();
if (!res.ok) {
let detail = text;
try {
const j = JSON.parse(text) as Problem;
if (j?.detail) detail = j.detail;
} catch {
/* plain text */
}
throw new Error(detail || `HTTP ${res.status}`);
}
if (!text) return undefined as T;
return JSON.parse(text) as T;
}