import { computed , inject , watch , InjectionKey , Ref , isRef } from 'vue-demi' ; import minifier from 'minify-groq' ; import type { SanityClient } from '@sanity/client' ; import type { QueryBuilder } from 'sanity-typed-queries' ; import { useCache , CacheOptions , FetchStatus } from './cache' ; export interface Client { fetch : ( query : string ) => Promise < any > ; [ key ] : any ; } export const clientSymbol = Symbol ( 'Sanity client' ) ; export const previewClientSymbol = Symbol ( 'Sanity client for previews' ) ; export const optionsSymbol = Symbol ( 'Default query options' ) ; type Query = string | ( ( ) => string | null | undefined | false ) ; interface Result < T > { /**
     * An automatically synced and updated result of the Sanity query.
     */ data : Ref < T > ; /**
     * The status of the query. Can be 'server loaded', 'loading', 'client loaded' or 'error'.
     */ status : Ref < FetchStatus > ; /**
     * An error returned in the course of fetching
     */ error : any ; /**
     * Get result directly from fetcher (integrates with cache)
     */ fetch : ( ) => Promise < T > ; } export type Options = Omit < CacheOptions < any > , 'initialValue' > & { /**
     * Whether to listen to real-time updates from Sanity. You can also pass an object of options to pass to `client.listen`. Defaults to false.
     */ listen ? : boolean | Record < string , any > ; } ; param query export function useSanityFetcher < T extends any > ( query ) ; param query param initialValue param mapper export function useSanityFetcher < T extends any , R extends any = T > ( query , initialValue , mapper ? , options ? ) ; export function useSanityFetcher ( query , initialValue = null , mapper = ( result ) => result , queryOptions ? ) { const client = inject ( clientSymbol ) ; const defaultOptions = inject ( optionsSymbol , { } ) ; const options = { ... defaultOptions , initialValue , ... queryOptions , } ; if ( ! client ) throw new Error ( 'You must call useSanityClient before using sanity resources in this project.' ) ; const computedQuery = typeof query === 'string' ? minifier ( query ) . replace ( /\n/g , ' ' ) : computed ( ( ) => minifier ( query ( ) || '' ) . replace ( /\n/g , ' ' ) ) ; const { data , status , setCache , error , fetch } = useCache ( computedQuery , query => query ? client . fetch ( query ) . then ( mapper ) : Promise . resolve ( initialValue ) , options ) ; if ( options . listen ) { const previewClient = inject ( previewClientSymbol , client as SanityClient ) ; if ( 'listen' in previewClient ) { const listenOptions = typeof options . listen === 'boolean' ? undefined : options . listen ; const subscribe = ( query ) => previewClient . listen ( query , listenOptions ) . subscribe ( event => event . result && setCache ( { key : query , value : event . result , } ) ) ; if ( isRef ( computedQuery ) ) { watch ( computedQuery , query => { const subscription = subscribe ( query ) ; const unwatch = watch ( computedQuery , newQuery => { if ( newQuery !== query ) { subscription . unsubscribe ( ) ; unwatch ( ) ; } } , { immediate : true } ) ; } , { immediate : true } ) ; } else { subscribe ( computedQuery ) ; } } } return { data , status , error , fetch } ; } export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string > ( builder ) ; export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string > ( builder , initialValue ) ; export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string , InitialValue > ( builder , initialValue ) ; export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string , Mapper extends ( result : ReturnType < Builder [ 'use' ] > [ 1 ] ) => any > ( builder , initialValue , mapper , options ? ) ; export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string , InitialValue , Mapper extends ( result : ReturnType < Builder [ 'use' ] > [ 1 ] ) => any > ( builder , initialValue , mapper , options ? ) ; export function useSanityQuery < Builder extends Pick < QueryBuilder < Schema , Mappings , Type , Project , Exclude > , 'use' > , Schema , Mappings extends Record < string , any > , Type , Project extends boolean , Exclude extends string > ( builder , initialValue = null , mapper = ( result ) => result , options ? ) { const query = 'use' in builder ? ( ) => builder . use ( ) [ 0 ] : ( ) => builder ( ) . use ( ) [ 0 ] ; const type = 'use' in builder ? builder . use ( ) [ 1 ] : builder ( ) . use ( ) [ 1 ] ; return useSanityFetcher < typeof type > ( query , initialValue || type , mapper , options ) ; }