upend/webui/src/lib/api.ts

141 lines
3.9 KiB
TypeScript

import LRU from "lru-cache";
import { UpListing, UpObject } from "upend";
import type {
Address,
IJob,
InEntry,
IValue,
ListingResult,
PutResult,
VaultInfo,
StoreInfo,
AttributeListingResult,
} from "upend/types";
import type { EntityListing } from "./entity";
export const API_URL = "api";
export async function fetchEntity(address: string): Promise<UpObject> {
const entityFetch = await fetch(`${API_URL}/obj/${address}`);
const entityResult = (await entityFetch.json()) as EntityListing;
const entityListing = new UpListing(entityResult.entries);
return entityListing.getObject(address);
}
export async function fetchEntry(address: string) {
const response = await fetch(`${API_URL}/raw/${address}`);
const data = await response.json();
const listing = new UpListing({ address: data });
return listing.entries[0];
}
const queryOnceLRU = new LRU<string, UpListing>(128);
const inFlightRequests: { [key: string]: Promise<UpListing> } = {};
export async function queryOnce(query: string): Promise<UpListing> {
const cacheResult = queryOnceLRU.get(query);
if (!cacheResult) {
if (!inFlightRequests[query]) {
console.debug(`Querying: ${query}`);
inFlightRequests[query] = new Promise((resolve, reject) => {
fetch(`${API_URL}/query`, {
method: "POST",
body: query,
keepalive: true,
})
.then(async (response) => {
resolve(new UpListing(await response.json()));
})
.catch((err) => reject(err));
});
} else {
console.debug(`Chaining request for ${query}...`);
}
return await inFlightRequests[query];
} else {
console.debug(`Returning cached: ${query}`);
return cacheResult;
}
}
export async function putEntry(entry: InEntry): Promise<PutResult> {
const response = await fetch(`${API_URL}/obj`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(entry),
});
return await response.json();
}
export async function putEntityAttribute(
entity: Address,
attribute: string,
value: IValue
): Promise<Address> {
const response = await fetch(`${API_URL}/obj/${entity}/${attribute}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(value),
});
return await response.json();
}
export async function uploadFile(file: File): Promise<PutResult> {
const formData = new FormData();
formData.append("file", file);
const response = await fetch(`${API_URL}/obj`, {
method: "PUT",
body: formData,
});
if (!response.ok) {
throw Error(await response.text());
}
return await response.json();
}
export async function deleteEntry(address: Address): Promise<void> {
await fetch(`${API_URL}/obj/${address}`, { method: "DELETE" });
}
export async function getRaw(address: Address, preview = false) {
return await fetch(`${API_URL}/${preview ? "thumb" : "raw"}/${address}`);
}
export async function refreshVault() {
return await fetch(`${API_URL}/refresh`, { method: "POST" });
}
export async function nativeOpen(address: Address) {
return fetch(`${API_URL}/raw/${address}?native=1`);
}
export async function fetchRoots(): Promise<ListingResult> {
const response = await fetch(`${API_URL}/hier_roots`);
return await response.json();
}
export async function fetchJobs(): Promise<IJob[]> {
const response = await fetch(`${API_URL}/jobs`);
return await response.json();
}
export async function fetchAllAttributes(): Promise<AttributeListingResult> {
const response = await fetch(`${API_URL}/all/attributes`);
return await response.json();
}
export async function fetchInfo(): Promise<VaultInfo> {
const response = await fetch(`${API_URL}/info`);
return await response.json();
}
export async function fetchStoreInfo(): Promise<StoreInfo> {
const response = await fetch(`${API_URL}/store`);
return await response.json();
}