import type { ProxyAccessor } from '../Cache' ; import type { InnerClientState , Refetch } from '../Client/client' ; import type { SelectionsBackup } from '../Selection/SelectionManager' ; import { decycle , isEmptyObject , isPlainObject , retrocycle } from '../Utils' ; export interface HydrateCacheOptions { /**
     * Cache snapshot, returned from `prepareRender`
     */ cacheSnapshot : string ; default shouldRefetch ? : boolean | number ; } export interface HydrateCache { ( { cacheSnapshot , shouldRefetch } ) : void ; } export interface PrepareRender { ( render ) : Promise < { cacheSnapshot : string ; } > ; } export interface SSRHelpers { hydrateCache : HydrateCache ; prepareRender : PrepareRender ; } export function createSSRHelpers ( { query , refetch , innerState , } ) { const hydrateCache = ( { cacheSnapshot , shouldRefetch = false , } ) => { try { const recoveredCache = retrocycle < { cache ? : Record < string , unknown > ; normalizedCache ? : Record < string , unknown > ; selections ? : SelectionsBackup ; } > ( JSON . parse ( cacheSnapshot ) ) ; if ( isPlainObject ( recoveredCache ) && isPlainObject ( recoveredCache . cache ) ) { const { selections , cache } = recoveredCache ; innerState . selectionManager . restore ( selections ) ; innerState . clientCache . mergeCache ( cache , 'query' ) ; if ( shouldRefetch ) { setTimeout ( ( ) => { refetch ( query ) . catch ( console . error ) ; } , typeof shouldRefetch === 'number' ? shouldRefetch : 0 ) ; } } } catch ( err ) { console . error ( err ) ; } } ; const prepareRender = async ( render ) => { const interceptor = innerState . interceptorManager . createInterceptor ( ) ; let prevIgnoreCache = innerState . allowCache ; try { innerState . allowCache = false ; await render ( ) ; } finally { innerState . interceptorManager . removeInterceptor ( interceptor ) ; innerState . allowCache = prevIgnoreCache ; } await Promise . all ( [ ... innerState . scheduler . pendingSelectionsGroupsPromises . values ( ) , ] ) ; const selections = innerState . selectionManager . backup ( ) ; const queryCache = innerState . clientCache . cache . query || { } ; const cache = { } ; for ( const { type , cachePath : [ , queryPath ] , } of interceptor . fetchSelections ) { if ( type === 0 ) { const value = queryCache [ queryPath ] ; if ( value !== undefined ) cache [ queryPath ] = value ; } } return { cacheSnapshot : JSON . stringify ( { ... decycle ( { cache : isEmptyObject ( cache ) ? undefined : cache , } ) , selections : selections [ 0 ] . length || selections [ 1 ] . length ? selections : undefined , } ) , } ; } ; return { hydrateCache , prepareRender , } ; }