149 lines
4.0 KiB
TypeScript
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;
|
|
}
|
|
} |