import type { Selection } from '../Selection' ; import { get , isObject , mergeWith , PlainObject , set } from '../Utils' ; import type { NormalizationHandler } from '../Normalization' ; export type CacheType = { query ? : Record < string , unknown > ; mutation ? : Record < string , unknown > ; subscription ? : Record < string , unknown > ; } ; export interface CacheInstance { cache : CacheType ; getCacheFromSelection : { < Value = unknown > ( selection ) : undefined | Value ; < Value = unknown , NotFound = undefined > ( selection , defaultValue ) : Value | NotFound ; } ; setCacheFromSelection : ( selection : Selection , value : unknown ) => void ; mergeCache : ( data : Record < string , unknown > , prefix : 'query' | 'mutation' | 'subscription' ) => void ; normalizedCache : Record < string , PlainObject | undefined > | undefined ; } export function createCache ( normalization ? ) { const cache = { } ; function getCacheFromSelection < Value = unknown > ( selection ) ; function getCacheFromSelection < Value = unknown , NotFound = undefined > ( selection , defaultValue ) ; function getCacheFromSelection < Value = unknown , NotFound = undefined > ( selection , notFoundValue = undefined ) { return normalization ? normalization . getCacheFromSelection < Value , NotFound > ( selection , notFoundValue , cache ) : get < Value , NotFound > ( cache , selection . cachePath , notFoundValue ) ; } function setCacheFromSelection ( selection , value ) { if ( normalization && isObject ( value ) ) normalization . scanNormalizedObjects ( value ) ; set ( cache , selection . cachePath , value ) ; } function onObjectMergeConflict ( currentValue , incomingValue ) { const result = normalization ?. onObjectMergeConflict ( currentValue , incomingValue ) ; if ( result ) return result ; if ( Array . isArray ( currentValue ) && Array . isArray ( incomingValue ) && currentValue . length !== incomingValue . length ) { return incomingValue ; } } function mergeCache ( data , prefix ) { normalization ?. scanNormalizedObjects ( data ) ; mergeWith < CacheType , CacheType > ( cache , { [ prefix ] : data } , onObjectMergeConflict ) ; } return { cache , getCacheFromSelection , setCacheFromSelection , mergeCache , normalizedCache : normalization ?. normalizedCache , } ; }