// import { useSWR } from "sswr"; import { useSWR } from "../util/fetch"; import { derived, Readable, readable, writable } from "svelte/store"; import type { IEntry, ListingResult, OrderedListing } from "upend/types"; import { listingAsOrdered, UpEntry } from "upend"; import LRU from "lru-cache"; export function useEntity( address: string | (() => string), condition?: () => Boolean ) { const { data, error, revalidate } = useSWR(() => condition === undefined || condition() ? `/api/obj/${typeof address === "string" ? address : address()}` : null ); const entries = derived(data, ($values) => $values ? listingAsOrdered($values) : [] ); const attributes = derived(entries, ($entries) => { const addr = typeof address === "string" ? address : address(); return $entries.filter(([_, e]) => e.entity === addr); }); const backlinks = derived(entries, ($entries) => { const addr = typeof address === "string" ? address : address(); return $entries.filter(([_, e]) => e.entity !== addr); }); return { entries, attributes, backlinks, data, error, revalidate, }; } export function query(query: () => string) { let queryString = typeof query === "string" ? query : query(); console.debug(`Querying: ${queryString}`); const { data, error, revalidate } = useSWR( () => `/api/obj?query=${query()}` ); const result = derived(data, ($values) => { return $values ? listingAsOrdered($values) : []; }); return { result, data, error, revalidate, }; } const queryOnceLRU = new LRU(128); const inFlightRequests: { [key: string]: Promise } = {}; export async function queryOnce(query: string): Promise { const cacheResult = queryOnceLRU.get(query); if (!cacheResult) { const url = `/api/obj?query=${query}`; let response; if (!inFlightRequests[url]) { console.debug(`Querying: ${query}`); inFlightRequests[url] = new Promise(async (resolve, reject) => { const response = await fetch(url, { keepalive: true }); resolve(listingAsOrdered(await response.json())); }); } else { console.debug(`Chaining request for ${query}...`); } return await inFlightRequests[url]; } else { console.debug(`Returning cached: ${query}`); return cacheResult; } } export async function identify( attributes: UpEntry[], backlinks: UpEntry[] ): Promise { // Get all entries where the object is linked const hasEntries = backlinks .filter((entry) => entry.attribute === "HAS") .map((entry) => entry.address); // Out of those relations, retrieve their ALIAS attrs const hasAliases = hasEntries.length ? await queryOnce( `(matches (in ${hasEntries.map((e) => `"${e}"`).join(" ")}) "ALIAS" ?)` ) : []; const aliasValues = hasAliases.map(([_, entry]) => String(entry.value.c)); // Return all LBLs concatenated with named aliases return attributes .filter((attr) => attr.attribute === "LBL") .map((attr) => String(attr.value.c)) .concat(aliasValues); }