frontend/classes/repo/ResourceRepo.ts
2025-11-08 10:41:33 +01:00

149 lines
4.0 KiB
TypeScript

import axios from "axios";
import type { Metadata } from "../Metadata";
import { ResourceEventType } from "./ResourceEventType";
import { AdvancedWebSocket } from "./AdvancedWebSocket";
import { WebsocketSession } from "./WebsocketSession";
export interface HasMetadata {
metadata: Metadata
}
export class ResourceEvent<T extends HasMetadata>
{
constructor (
public type: ResourceEventType,
public resources: T[]
) {}
}
export class ResourceRepo<T extends HasMetadata>
{
private resources: Ref<T[] | undefined> = ref(undefined);
private websocket?: AdvancedWebSocket;
static init<T extends HasMetadata>()
{
return new ResourceRepo<T>();
}
listen(resource: string)
{
WebsocketSession.get((token: string) => {
const webSocket = AdvancedWebSocket.open(StringUtils.format("%s/watch/%s/%s?token=%s", ApiConfig.getWsBase(), resource, this.getNamespace(), token),
(event) => {
const data = JSON.parse(event.data) as ResourceEvent<T>;
switch (data.type)
{
case ResourceEventType.INIT:
{
this.add(data.resources);
break;
}
case ResourceEventType.ADDED:
{
this.add(data.resources);
break;
}
case ResourceEventType.MODIFIED:
{
this.update(data.resources);
break;
}
case ResourceEventType.DELETED:
{
this.delete(data.resources);
break;
}
}
},
() => { }
);
this.websocket = webSocket;
});
}
private add(resources: T[])
{
if (this.resources.value == null)
{
this.resources.value = [];
}
this.resources.value.push(...resources);
}
private delete(resources: T[])
{
if (this.resources.value == null)
{
this.resources.value = [];
}
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[])
{
if (this.resources.value == null)
{
this.resources.value = [];
}
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()
{
if (this.websocket)
{
this.websocket.close();
}
}
get()
{
return computed(() => {
if (this.resources.value)
{
return this.resources.value.toSorted((a, b) => a.metadata.name.localeCompare(b.metadata.name));
}
return undefined;
})
}
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<T[]>(url)
.then((response) => {
this.resources.value = response.data;
});
}
private getNamespace()
{
return useRoute().params.namespace as string;
}
}