import {maybe} from '@freckle/maybe' import {exhaustive} from '@freckle/exhaustive' export type ResourceStatusT = | { status: 'idle' } | { status: 'loading' } | { status: 'reloading' data: R } | { status: 'error' error: unknown } | { status: 'complete' data: R hasUpdated: boolean } | { status: 'updating' data: R } | { status: 'updating-error' data: R error: unknown } export function fromMaybeResourceData(resource: ResourceStatusT, defaultData: R): R { return maybeResourceData(resource) ?? defaultData } export function maybeResourceData(resource: ResourceStatusT): R | undefined | null { switch (resource.status) { case 'idle': return null case 'loading': return null case 'reloading': return resource.data case 'error': return null case 'complete': return resource.data case 'updating': return resource.data case 'updating-error': return resource.data default: return exhaustive(resource) } } export function isFetching(resource: ResourceStatusT): boolean { return resource.status === 'loading' || resource.status === 'reloading' } export const updateResource = ( resource: ResourceStatusT, update: (data: R) => R ): ResourceStatusT => { const mData = maybeResourceData(resource) return maybe( () => resource, data => ({ status: 'complete', data: update(data), hasUpdated: false // This is used for async updates, e.g. from a fetch response }), mData ) }