import { defineStore } from "pinia"; import { ref, shallowRef } from "vue"; import { SSEManager, SSEMessageResource } from "@/SSEManager"; import { useSessionStore } from "@/store/session"; import { apiClient } from "@/client"; import { Communication, type CommunicationDTO, Contact, type ContactDTO, PublicReport, type PublicReportDTO, } from "@/type/api"; interface uriHaver { uri: string; } type jsonConverter = (arg: dto) => full; function createResourceStore( resource_name: string, api_base: string, from_json: jsonConverter, ) { const _resourceByURI = shallowRef>(new Map()); const _resourceFetchAll = ref | null>(null); const _resourceFetchByURI = shallowRef | null>>( new Map(), ); // Subscription SSEManager.subscribe((msg: SSEMessageResource) => { if (msg.resource.startsWith(resource_name) && msg.type == "updated") { fetchByURI(msg.uri); } }); async function byAll(): Promise { const cur = _resourceFetchAll.value; if (cur) { return cur; } return fetchAll(); } async function byID(id: string): Promise { const uri = uriFromID(id); return byURI(uri); } async function byURI(uri: string): Promise { let cur = _resourceFetchByURI.value.get(uri); if (cur) { return cur; } cur = fetchByURI(uri); _resourceFetchByURI.value.set(uri, cur); return cur; } async function fetchAll(): Promise { /* const sessionStore = useSessionStore(); const session = await sessionStore.get(); const params = new URLSearchParams(); params.append("sort", "-created"); const url = `${session.urls.api.mailer}?${params}`; */ const url = `/api${api_base}`; const dtos = (await apiClient.JSONGet(url)) as dto[]; const resources = dtos.map((m: dto) => from_json(m)); resources.forEach((r: full) => { _resourceByURI.value.set(r.uri, r); }); return resources; } async function fetchByID(id: string): Promise { const uri = uriFromID(id); return fetchByURI(uri); } async function fetchByURI(uri: string): Promise { try { const response = await fetch(uri); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const body: dto = await response.json(); const report = from_json(body); _resourceByURI.value.set(report.uri, report); return report; } catch (err) { console.error("Error loading users:", err); throw err; } } function loadingAll(): boolean { return !!_resourceFetchAll.value; } function loadingURI(uri: string): boolean { return !!_resourceFetchByURI.value.get(uri); } function uriFromID(id: string): string { return `${api_base}/${id}`; } return { byAll, byID, byURI, fetchAll, fetchByID, fetchByURI, loadingAll, loadingURI, }; } export const useStoreResource = defineStore("resource", () => { return { communication: createResourceStore( "sync:communication", "/communication", Communication.fromJSON, ), contact: createResourceStore( "sync:contact", "/contact", Contact.fromJSON, ), publicreport: createResourceStore( "sync:publicreport", "/publicreport", PublicReport.fromJSON, ), }; });