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
}