mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-05-27 09:32:28 +02:00
239 lines
5.9 KiB
TypeScript
239 lines
5.9 KiB
TypeScript
import { controlPlaneJson } from '@/lib/controlPlane';
|
|
|
|
export interface PrivacyProfileSnapshot {
|
|
profile?: string;
|
|
wormhole_enabled?: boolean;
|
|
}
|
|
|
|
export interface RnsStatusSnapshot {
|
|
enabled: boolean;
|
|
ready: boolean;
|
|
configured_peers: number;
|
|
active_peers: number;
|
|
}
|
|
|
|
export interface InfonetBootstrapSnapshot {
|
|
node_mode?: string;
|
|
manifest_loaded?: boolean;
|
|
manifest_signer_id?: string;
|
|
manifest_valid_until?: number;
|
|
bootstrap_peer_count?: number;
|
|
sync_peer_count?: number;
|
|
push_peer_count?: number;
|
|
operator_peer_count?: number;
|
|
bootstrap_seed_peer_count?: number;
|
|
default_sync_peer_count?: number;
|
|
last_bootstrap_error?: string;
|
|
}
|
|
|
|
export interface InfonetSyncRuntimeSnapshot {
|
|
last_sync_started_at?: number;
|
|
last_sync_finished_at?: number;
|
|
last_sync_ok_at?: number;
|
|
next_sync_due_at?: number;
|
|
last_peer_url?: string;
|
|
last_error?: string;
|
|
last_outcome?: string;
|
|
current_head?: string;
|
|
fork_detected?: boolean;
|
|
consecutive_failures?: number;
|
|
}
|
|
|
|
export interface InfonetPushResultSnapshot {
|
|
peer_url?: string;
|
|
ok?: boolean;
|
|
error?: string;
|
|
transport?: string;
|
|
}
|
|
|
|
export interface InfonetPushRuntimeSnapshot {
|
|
last_event_id?: string;
|
|
last_push_ok_at?: number;
|
|
last_push_error?: string;
|
|
last_results?: InfonetPushResultSnapshot[];
|
|
}
|
|
|
|
export interface InfonetNodeStatusSnapshot {
|
|
network_id?: string;
|
|
total_events?: number;
|
|
active_events?: number;
|
|
known_nodes?: number;
|
|
author_nodes?: number;
|
|
registered_nodes?: number;
|
|
chain_size_kb?: number;
|
|
head_hash?: string;
|
|
unsigned_events?: number;
|
|
valid?: boolean;
|
|
validation?: string;
|
|
event_types?: Record<string, number>;
|
|
node_mode?: string;
|
|
node_enabled?: boolean;
|
|
bootstrap?: InfonetBootstrapSnapshot;
|
|
sync_runtime?: InfonetSyncRuntimeSnapshot;
|
|
push_runtime?: InfonetPushRuntimeSnapshot;
|
|
private_lane_tier?: string;
|
|
private_transport_required?: boolean;
|
|
}
|
|
|
|
export interface NodeSettingsSnapshot {
|
|
enabled?: boolean;
|
|
timemachine_enabled?: boolean;
|
|
updated_at?: number;
|
|
node_mode?: string;
|
|
node_enabled?: boolean;
|
|
}
|
|
|
|
export interface TorHiddenServiceSnapshot {
|
|
ok?: boolean;
|
|
running?: boolean;
|
|
onion_address?: string;
|
|
detail?: string;
|
|
}
|
|
|
|
const CACHE_TTL_MS = 5000;
|
|
|
|
type CacheEntry<T> = {
|
|
value: T;
|
|
expiresAt: number;
|
|
inflight: Promise<T> | null;
|
|
} | null;
|
|
|
|
let privacyProfileCache: CacheEntry<PrivacyProfileSnapshot> = null;
|
|
let rnsStatusCache: CacheEntry<RnsStatusSnapshot> = null;
|
|
let infonetNodeStatusCache: CacheEntry<InfonetNodeStatusSnapshot> = null;
|
|
|
|
function loadPrivacyProfile(): Promise<PrivacyProfileSnapshot> {
|
|
return controlPlaneJson<PrivacyProfileSnapshot>('/api/settings/privacy-profile', {
|
|
requireAdminSession: false,
|
|
});
|
|
}
|
|
|
|
async function loadRnsStatus(): Promise<RnsStatusSnapshot> {
|
|
const data = await controlPlaneJson<Partial<RnsStatusSnapshot>>('/api/mesh/rns/status', {
|
|
requireAdminSession: false,
|
|
});
|
|
return {
|
|
enabled: Boolean(data?.enabled),
|
|
ready: Boolean(data?.ready),
|
|
configured_peers: Number(data?.configured_peers || 0),
|
|
active_peers: Number(data?.active_peers || 0),
|
|
};
|
|
}
|
|
|
|
function loadInfonetNodeStatus(): Promise<InfonetNodeStatusSnapshot> {
|
|
return controlPlaneJson<InfonetNodeStatusSnapshot>('/api/mesh/infonet/status', {
|
|
requireAdminSession: false,
|
|
});
|
|
}
|
|
|
|
function loadNodeSettings(): Promise<NodeSettingsSnapshot> {
|
|
return controlPlaneJson<NodeSettingsSnapshot>('/api/settings/node', {
|
|
requireAdminSession: false,
|
|
});
|
|
}
|
|
|
|
async function resolveCached<T>(
|
|
cache: CacheEntry<T>,
|
|
loader: () => Promise<T>,
|
|
setCache: (value: CacheEntry<T>) => void,
|
|
force: boolean,
|
|
): Promise<T> {
|
|
const now = Date.now();
|
|
if (!force && cache?.value && cache.expiresAt > now) {
|
|
return cache.value;
|
|
}
|
|
if (!force && cache?.inflight) {
|
|
return cache.inflight;
|
|
}
|
|
const inflight = loader()
|
|
.then((value) => {
|
|
setCache({
|
|
value,
|
|
expiresAt: Date.now() + CACHE_TTL_MS,
|
|
inflight: null,
|
|
});
|
|
return value;
|
|
})
|
|
.catch((error) => {
|
|
setCache(cache ? { ...cache, inflight: null } : null);
|
|
throw error;
|
|
});
|
|
setCache({
|
|
value: cache?.value as T,
|
|
expiresAt: 0,
|
|
inflight,
|
|
});
|
|
return inflight;
|
|
}
|
|
|
|
export function invalidatePrivacyProfileCache(): void {
|
|
privacyProfileCache = null;
|
|
}
|
|
|
|
export function invalidateRnsStatusCache(): void {
|
|
rnsStatusCache = null;
|
|
}
|
|
|
|
export function invalidateInfonetNodeStatusCache(): void {
|
|
infonetNodeStatusCache = null;
|
|
}
|
|
|
|
export async function fetchPrivacyProfileSnapshot(
|
|
force: boolean = false,
|
|
): Promise<PrivacyProfileSnapshot> {
|
|
return resolveCached(
|
|
privacyProfileCache,
|
|
loadPrivacyProfile,
|
|
(value) => {
|
|
privacyProfileCache = value;
|
|
},
|
|
force,
|
|
);
|
|
}
|
|
|
|
export async function fetchRnsStatusSnapshot(force: boolean = false): Promise<RnsStatusSnapshot> {
|
|
return resolveCached(
|
|
rnsStatusCache,
|
|
loadRnsStatus,
|
|
(value) => {
|
|
rnsStatusCache = value;
|
|
},
|
|
force,
|
|
);
|
|
}
|
|
|
|
export async function fetchInfonetNodeStatusSnapshot(
|
|
force: boolean = false,
|
|
): Promise<InfonetNodeStatusSnapshot> {
|
|
return resolveCached(
|
|
infonetNodeStatusCache,
|
|
loadInfonetNodeStatus,
|
|
(value) => {
|
|
infonetNodeStatusCache = value;
|
|
},
|
|
force,
|
|
);
|
|
}
|
|
|
|
export async function fetchNodeSettingsSnapshot(): Promise<NodeSettingsSnapshot> {
|
|
return loadNodeSettings();
|
|
}
|
|
|
|
export async function setInfonetNodeEnabled(enabled: boolean): Promise<NodeSettingsSnapshot> {
|
|
const result = await controlPlaneJson<NodeSettingsSnapshot>('/api/settings/node', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ enabled }),
|
|
requireAdminSession: false,
|
|
});
|
|
invalidateInfonetNodeStatusCache();
|
|
return result;
|
|
}
|
|
|
|
export async function startTorHiddenService(): Promise<TorHiddenServiceSnapshot> {
|
|
return controlPlaneJson<TorHiddenServiceSnapshot>('/api/settings/tor/start', {
|
|
method: 'POST',
|
|
requireAdminSession: false,
|
|
});
|
|
}
|