import { createCache } from "../cache.ts"; import { MARKA_API_KEY, MARKA_API_URL } from "../env.ts"; import { getImage } from "../image.ts"; import { GenericResource } from "./schema.ts"; async function addImageToResource( resource: GenericResource, ): Promise { const imageUrl = resource?.content?.image; if (imageUrl) { try { const absoluteImageUrl = (imageUrl.startsWith("https://") || imageUrl.startsWith("http://")) ? imageUrl : `${MARKA_API_URL}/${imageUrl}`; const image = await getImage(absoluteImageUrl); return { ...resource, image } as T; } catch (e) { console.log(`Failed to fetch image: ${imageUrl}`, e); } } return resource as T; } type Resource = GenericResource & { content: GenericResource["content"] & Array; }; const fetchCache = createCache("marka"); const cacheLock = new Map>(); async function fetchAndStoreUrl(url: string) { const response = await fetch(url); if (!response.ok) { throw new Error(`Failed to fetch resource: ${response.status}`); } const res = await response.json(); fetchCache.set(url, res); return res; } async function cachedFetch( url: string, ): Promise { if (fetchCache.has(url)) { fetchAndStoreUrl(url); // Fetch the url in the background return fetchCache.get(url); } if (cacheLock.has(url)) return cacheLock.get(url); const response = fetchAndStoreUrl(url); cacheLock.set(url, response); const res = await response; cacheLock.delete(url); return res; } export async function fetchResource( resource: string, ): Promise { try { const d = `${MARKA_API_URL}/resources/${resource}`; const res = await cachedFetch(d); if (!res) return; return addImageToResource(res); } catch (_e) { return; } } export async function listResources( resource: string, ): Promise { try { const d = `${MARKA_API_URL}/resources/${resource}`; const list = await cachedFetch(d); if (!list) return []; return Promise.all( list?.content .filter((a) => a?.content?._type) .map((res) => addImageToResource(res) as Promise), ); } catch (_e) { console.log(`Failed to fetch resource: ${resource}`, _e); return []; } } export async function createResource( path: string, content: string | object | ArrayBuffer, ) { const isJson = typeof content === "object" && !(content instanceof ArrayBuffer); const fetchUrl = `${MARKA_API_URL}/resources/${path}`; const headers = new Headers(); headers.append("Content-Type", isJson ? "application/json" : ""); if (MARKA_API_KEY) { headers.append("Authentication", MARKA_API_KEY); } const response = await fetch(fetchUrl, { method: "POST", headers, body: isJson ? JSON.stringify(content) : content, }); if (!response.ok) { const text = await response.text(); throw new Error( `failed to create resource (resources/${path}): ${ text || response.status }`, ); } return response.json(); }