import { type Ref } from 'vue'; export type ResourceFetcher = (signal: AbortSignal) => Promise; /** Controls the resource's startup behavior. * * - `'immediate'` (default) — fire the fetcher synchronously at creation; * `loading.value` starts `true`. * - `'pending'` — don't fire the fetcher yet, but render as if a fetch is * coming: `loading.value` starts `true`. Pair with a manual `refresh()` * call from `onMounted` (or wherever the dependencies become available). * Use this when the fetcher depends on state set after setup runs (e.g. a * route param resolved asynchronously) — it avoids the blank-frame flash * you'd get from `'idle'`. * - `'idle'` — don't fire the fetcher and don't pretend you will: * `loading.value` starts `false`. The resource is dormant until * `refresh()` or `mutate()` is called. */ export type ResourceStart = 'immediate' | 'pending' | 'idle'; export type ResourceOptions = { /** When and how the fetcher fires on creation. Default: `'immediate'`. */ start?: ResourceStart; }; export type ResourceMutator = T | null | ((prev: T | null) => T | null); export type Resource = { /** Latest resolved value, or `null` before the first successful load. */ data: Ref; /** Latest rejection reason, or `null` when the resource is healthy. */ error: Ref; /** True while a fetch is in flight, or when `start: 'pending'` was set * and `refresh()` hasn't been called yet. */ loading: Ref; /** Re-runs the fetcher. Any in-flight request is aborted first. */ refresh: () => Promise; /** Aborts the in-flight request, if any. No-op otherwise. */ cancel: () => void; /** Imperatively write the data ref without re-fetching. Accepts a new * value or an updater function. Use after an edit action returns the new * entity, so you avoid a wasteful re-fetch. Pending fetches are aborted * so a slower response can't clobber the mutation. */ mutate: (next: ResourceMutator) => void; }; /** Ref-backed async data composable for AbsoluteJS Vue pages. Replaces the * hand-rolled `onMounted(() => { loading.value = true; data.value = await * fetch(); })` + `ref` boilerplate with a single call that also handles * abort-on-teardown, refresh, and optimistic mutation. * * This is a per-component LOADER, not a cross-component cache — every call * owns its own state and refetches on creation. For data that should survive * navigation / be shared across components (so revisiting a route doesn't * refetch), use a cache layer (e.g. TanStack Query) or `@absolutejs/sync` * instead. Reach for `useResource` when a one-shot, component-scoped fetch is * exactly what you want. * * ```ts * const profile = useResource((signal) => api.profile.me.get({ signal })); * * // in template: * // * //

{{ profile.data.value.name }}

* ``` * * The fetcher receives an `AbortSignal` it can pass to `fetch` — the signal * aborts when the owning effect scope is disposed (component unmount) or on a * new `refresh()` call. Call it during `setup()` so an effect scope is * active; teardown won't be wired up otherwise. */ export declare const useResource: (fetcher: ResourceFetcher, options?: ResourceOptions) => Resource;