import { GQtyClient , GQtyError , prepass } from 'gqty' ; import * as React from 'react' ; import { OnErrorHandler , useInterceptSelections , useIsomorphicLayoutEffect , } from '../common' ; import type { ReactClientOptionsWithDefaults } from '../utils' ; export interface UseQueryPrepareHelpers < GeneratedSchema extends { query : object ; } > { readonly prepass : typeof prepass ; readonly query : GeneratedSchema [ 'query' ] ; } export interface UseQueryOptions < GeneratedSchema extends { query : object ; } = never > { suspense ? : boolean ; staleWhileRevalidate ? : boolean | object | number | string | null ; onError ? : OnErrorHandler ; prepare ? : ( helpers : UseQueryPrepareHelpers < GeneratedSchema > ) => void ; } export interface UseQueryState { /**
     * Useful for `Non-Suspense` usage.
     */ readonly isLoading : boolean ; /**
     * Latest scheduler Error, for more in-depth error management use `useMetaState` hook
     */ error ? : GQtyError ; } export type UseQueryReturnValue < GeneratedSchema extends { query : object ; } > = GeneratedSchema [ 'query' ] & { $state : UseQueryState ; } ; export interface UseQuery < GeneratedSchema extends { query : object ; } > { ( options ? ) : UseQueryReturnValue < GeneratedSchema > ; } export function createUseQuery < GeneratedSchema extends { query : object ; mutation : object ; subscription : object ; } > ( client , opts ) { const { suspense : defaultSuspense , staleWhileRevalidate : defaultStaleWhileRevalidate , } = opts . defaults ; const { scheduler , eventHandler , interceptorManager } = client ; const clientQuery = client . query ; const prepareHelpers = { prepass , query : clientQuery , } ; type Writeable < T > = { - readonly [ P in keyof T ] : T [ P ] ; } ; const errorsMap = scheduler . errors . map ; const getLastError = ( ) => Array . from ( errorsMap . values ( ) ) . pop ( ) ; const useQuery = function useQuery ( { suspense = defaultSuspense , staleWhileRevalidate = defaultStaleWhileRevalidate , onError , prepare , } = { } ) : UseQueryReturnValue < GeneratedSchema > { const [ $state ] = React . useState < Writeable < UseQueryState > > ( ( ) => { const state = { isLoading : true , } ; const error = getLastError ( ) ; if ( error ) state . error = error ; return state ; } ) ; const { unsubscribe , fetchingPromise } = useInterceptSelections ( { staleWhileRevalidate , eventHandler , interceptorManager , scheduler , onError , updateOnFetchPromise : true , } ) ; if ( prepare ) { try { prepare ( prepareHelpers ) ; } catch ( err ) { if ( err instanceof Error && Error . captureStackTrace ! ) { Error . captureStackTrace ( err , useQuery ) ; } throw err ; } } useIsomorphicLayoutEffect ( ( ) => { return scheduler . errors . subscribeErrors ( ( ev ) => { switch ( ev . type ) { case 'errors_clean' : case 'new_error' : const error = getLastError ( ) ; if ( error ) { $state . error = error ; } else { delete $state . error ; } } } ) ; } , [ ] ) ; useIsomorphicLayoutEffect ( unsubscribe ) ; if ( fetchingPromise . current ) { $state . isLoading = true ; if ( suspense ) throw fetchingPromise . current ; } else { $state . isLoading = false ; } return React . useMemo < UseQueryReturnValue < GeneratedSchema > > ( ( ) => { const gqtyProxy = Symbol ( 'gqty-proxy' ) ; return new Proxy ( Object . keys ( clientQuery ) . reduce ( ( acum , value ) => { acum [ value ] = gqtyProxy ; return acum ; } , { $state , } ) , { set ( _t , key , value ) { return Reflect . set ( clientQuery , key , value ) ; } , get ( _t , key ) { if ( key === '$state' ) return $state ; return Reflect . get ( clientQuery , key ) ; } , } ) ; } , [ $state ] ) ; } ; return useQuery ; }