From 51da827089c48f31b98dc91fb9282a572c636b27 Mon Sep 17 00:00:00 2001 From: Jannis Braun <151788261+TheZwiss@users.noreply.github.com> Date: Sun, 26 Apr 2026 22:32:36 +0200 Subject: [PATCH] feat(web): API client methods for peering subscriptions and notifications - Drops the web-local ApprovalRequest interface in favor of the canonical shared type (Task 2 already established this; Task 10 reconciles the consumer side). - Adds five new federation methods wrapping the REST endpoints added in Tasks 8 and 9: peeringSubscriptions (GET), cancelPeering Subscription (DELETE), peeringNotifications (GET +/- unreadOnly filter), markPeeringNotificationRead (POST :id/read), markAll PeeringNotificationsRead (POST read-all). --- packages/web/src/api/client.ts | 39 ++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/packages/web/src/api/client.ts b/packages/web/src/api/client.ts index e2360f9f..d80d49e0 100644 --- a/packages/web/src/api/client.ts +++ b/packages/web/src/api/client.ts @@ -53,9 +53,12 @@ import type { FederationIdentityDeleteRequest, FederationIdentityDeleteResponse, FederationPeer, + ApprovalRequest, + PeeringSubscription, + PeeringNotification, } from '@backspace/shared'; -export type { FederationPeer }; +export type { FederationPeer, ApprovalRequest, PeeringSubscription, PeeringNotification }; export class RateLimitError extends Error { readonly retryAfter: number; @@ -66,14 +69,6 @@ export class RateLimitError extends Error { } } -export interface ApprovalRequest { - id: string; - origin: string; - instanceName: string | null; - requestedAt: number; - expiresAt: number; -} - export class BackspaceApiClient { readonly auth: { register: (data: RegisterRequest) => Promise; @@ -230,6 +225,11 @@ export class BackspaceApiClient { approvalRequests: () => Promise<{ requests: ApprovalRequest[] }>; approveRequest: (id: string) => Promise<{ success: boolean; peer?: FederationPeer }>; denyRequest: (id: string) => Promise<{ success: boolean }>; + peeringSubscriptions: () => Promise<{ subscriptions: PeeringSubscription[] }>; + cancelPeeringSubscription: (id: string) => Promise<{ success: boolean }>; + peeringNotifications: (unreadOnly?: boolean) => Promise<{ notifications: PeeringNotification[] }>; + markPeeringNotificationRead: (id: string) => Promise<{ success: boolean }>; + markAllPeeringNotificationsRead: () => Promise<{ success: boolean; count: number }>; }; readonly admin: { @@ -697,6 +697,27 @@ export class BackspaceApiClient { request<{ success: boolean }>( 'POST', `/federation/approval-requests/${id}/deny` ), + peeringSubscriptions: () => + request<{ subscriptions: PeeringSubscription[] }>( + 'GET', '/federation/peering-subscriptions' + ), + cancelPeeringSubscription: (id: string) => + request<{ success: boolean }>( + 'DELETE', `/federation/peering-subscriptions/${id}` + ), + peeringNotifications: (unreadOnly = false) => + request<{ notifications: PeeringNotification[] }>( + 'GET', + `/federation/peering-notifications${unreadOnly ? '?unread=1' : ''}`, + ), + markPeeringNotificationRead: (id: string) => + request<{ success: boolean }>( + 'POST', `/federation/peering-notifications/${id}/read` + ), + markAllPeeringNotificationsRead: () => + request<{ success: boolean; count: number }>( + 'POST', '/federation/peering-notifications/read-all' + ), }; this.admin = {