import axios from "axios"; import type { Metadata } from "./Metadata"; export interface HasMetadata { metadata: Metadata } export class ResourceEvent { constructor ( public type: string, public resources: T[] ) {} } export class ResourceRepo { private resources: Ref = ref([]); private interval: NodeJS.Timeout | undefined = undefined; private websocket: WebSocket | undefined = undefined; static init() { return new ResourceRepo(); } listen(resource: string) { const websocket = new WebSocket(StringUtils.format("%s/watch/%s/%s", ApiConfig.getWsBase(), resource, this.getNamespace())); websocket.addEventListener('open', () => { console.info("Opened Websocket."); }) websocket.addEventListener("message", (event) => { const data = JSON.parse(event.data) as ResourceEvent; console.info(StringUtils.format("[%s] Resource", data.type)); switch (data.type) { case "INIT": { this.add(data.resources); break; } case "ADDED": { this.add(data.resources); break; } case "MODIFIED": { this.update(data.resources); break; } case "DELETED": { this.delete(data.resources); break; } } }); const interval = setInterval(() => { console.info("[PING]"); websocket.send('[PING]'); }, 5000); websocket.addEventListener("close", () => { console.info("Closing websocket."); clearTimeout(interval); }); this.websocket = websocket; } private add(resources: T[]) { this.resources.value.push(...resources); } private delete(resources: T[]) { for (const resource of resources) { const index = this.resources.value.findIndex(item => item.metadata.uid === resource.metadata.uid); if (index != null) { this.resources.value.splice(index, 1); } } } private update(resources: T[]) { for (const resource of resources) { const index = this.resources.value.findIndex(item => item.metadata.uid === resource.metadata.uid); if (index != null) { this.resources.value[index] = resource; } } } load(resourceType: string) { this.refresh(resourceType); return this; } clear() { clearTimeout(this.interval); if (this.websocket != null) { this.websocket.close(); } } get() { return computed(() => { return this.resources.value.toSorted((a, b) => a.metadata.name.localeCompare(b.metadata.name)); }) } private refresh(resourceType: string) { const namespace = this.getNamespace(); let url = StringUtils.format("%s/resources/%s", ApiConfig.getHttpBase(), resourceType); if (namespace) { url = StringUtils.format("%s/%s", url, namespace); } axios.get(url) .then((response) => { this.resources.value = response.data; }); } private getNamespace() { return useRoute().params.namespace as string; } }