import type { Renderable } from 'dhtml' import { invalidate, onMount } from 'dhtml/client' import type { Bus } from './bus' import { suspend } from './suspense' export interface Query { (): T revalidate(): void } type QueryFn = (prev: T | null) => Promise export function createQuery(renderable: Renderable, fn: QueryFn): Query { let value: T | null = null let promise = handle() async function handle() { value = await fn(value) invalidate(renderable) return value } function query() { if (value == null) return suspend(renderable, promise) return value } query.revalidate = () => { promise = handle() } return query } export function createSubscribedQuery( renderable: Renderable, bus: Bus, event: Event, fn: QueryFn, ): Query { const query = createQuery(renderable, fn) onMount(renderable, () => bus.subscribe(event, query.revalidate)) return query }