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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
export type ModuleRow = {
|
||||
id: string;
|
||||
type: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
priority: number;
|
||||
refresh_interval_sec: number;
|
||||
cron_expr: string;
|
||||
default_community_id: string | null;
|
||||
doh_profile_id: string | null;
|
||||
};
|
||||
|
||||
export type ModulesResponse = {
|
||||
items: ModuleRow[];
|
||||
next_cursor: string | null;
|
||||
has_more: boolean;
|
||||
};
|
||||
|
||||
export type RevisionRow = {
|
||||
id: string;
|
||||
content_hash: string;
|
||||
created_at: string;
|
||||
parent_revision_id: string | null;
|
||||
materialized_prefix_count: number;
|
||||
module_id: string | null;
|
||||
};
|
||||
|
||||
export type RevisionsResponse = {
|
||||
items: RevisionRow[];
|
||||
next_cursor: string | null;
|
||||
has_more: boolean;
|
||||
};
|
||||
|
||||
export type PeerRow = {
|
||||
id: string;
|
||||
name: string;
|
||||
neighbor: string;
|
||||
session_state: string;
|
||||
bgp_speaker_id: string | null;
|
||||
};
|
||||
|
||||
export type PeersResponse = {
|
||||
items: PeerRow[];
|
||||
next_cursor: string | null;
|
||||
has_more: boolean;
|
||||
};
|
||||
|
||||
export type SpeakerRow = {
|
||||
id: string;
|
||||
role: string;
|
||||
endpoint: string;
|
||||
last_applied_revision_id: string | null;
|
||||
};
|
||||
|
||||
export type SpeakersResponse = {
|
||||
items: SpeakerRow[];
|
||||
next_cursor: string | null;
|
||||
has_more: boolean;
|
||||
};
|
||||
|
||||
export type JobRow = {
|
||||
job_id: string;
|
||||
kind: string;
|
||||
status: string;
|
||||
idempotency_key?: string | null;
|
||||
created_at?: string;
|
||||
started_at?: string | null;
|
||||
finished_at?: string | null;
|
||||
error?: string | null;
|
||||
meta?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type JobsResponse = {
|
||||
items: JobRow[];
|
||||
next_cursor: string | null;
|
||||
has_more: boolean;
|
||||
};
|
||||
Reference in New Issue
Block a user