import { StoreObject } from "@apollo/client/core" ; import EntityTypeMap from "./EntityTypeMap" ; import { NormalizedCacheObjectWithInvalidation } from "./types" ; import { makeEntityId , isQuery } from "../helpers" ; import { Policies } from '@apollo/client/cache/inmemory/policies' ; import { cacheExtensionsCollectionTypename } from '../cache/utils' ; interface EntityStoreWatcherConfig { entityStore : any ; entityTypeMap : EntityTypeMap ; policies : Policies ; updateCollectionField : ( typename : string , dataId : string ) => void ; } type EntityStoreWatcherStoreFunctions = { clear : any ; delete : any ; merge : any ; replace : any ; } ; /**
 * Watches the EntityStore for changes and performs side-effects to keep the EntityTypeMap synchronized with the data in the EntityStore.
 */ export default class EntityStoreWatcher { private storeFunctions : EntityStoreWatcherStoreFunctions ; constructor ( private config ) { const { entityStore : { clear , delete : deleteKey , merge , replace } , } = this . config ; this . storeFunctions = { clear , delete : deleteKey , merge , replace , } ; this . watch ( ) ; } private delete = ( dataId , fieldName ? , args ? ) => { const { entityStore , entityTypeMap , policies } = this . config ; const result = this . storeFunctions . delete . call ( entityStore , dataId , fieldName , args ) ; const entity = entityTypeMap . readEntityById ( makeEntityId ( dataId , fieldName ) ) ; const storeFieldName = fieldName && args ? policies . getStoreFieldName ( { typename : entity ? entity . typename : undefined , fieldName , args , } ) : undefined ; entityTypeMap . evict ( dataId , storeFieldName || fieldName ) ; return result ; } ; private merge = ( dataId , incomingStoreObject ) => { const { entityStore , entityTypeMap } = this . config ; if ( isQuery ( dataId ) ) { Object . keys ( incomingStoreObject ) . filter ( ( storeFieldName ) => storeFieldName !== "__typename" && ( incomingStoreObject [ storeFieldName ] as StoreObject ) ?. __typename ) . forEach ( ( storeFieldName ) => { const entityStoreObject = incomingStoreObject [ storeFieldName ] as StoreObject ; entityTypeMap . write ( entityStoreObject . __typename ! , dataId , storeFieldName ) ; } ) ; } else { const typename = incomingStoreObject . __typename ; if ( dataId && typename && typename !== cacheExtensionsCollectionTypename ) { this . config . updateCollectionField ( typename , dataId ) ; entityTypeMap . write ( typename , dataId ) ; } } return this . storeFunctions . merge . call ( entityStore , dataId , incomingStoreObject ) ; } ; private clear = ( ) => { const { config : { entityStore , entityTypeMap } , storeFunctions , } = this ; entityTypeMap . clear ( ) ; storeFunctions . clear . call ( entityStore ) ; } ; private replace = ( data ) => { const { config : { entityStore , entityTypeMap } , storeFunctions : { replace } , } = this ; const invalidation = data ?. invalidation ; if ( ! data || ! invalidation ) { replace . call ( entityStore , data ) ; return ; } delete data . invalidation ; entityTypeMap . restore ( invalidation . entitiesById ) ; this . pause ( ) ; replace . call ( entityStore , data ) ; this . watch ( ) ; } ; private watch ( ) { const { entityStore } = this . config ; entityStore . clear = this . clear ; entityStore . delete = this . delete ; entityStore . merge = this . merge ; entityStore . replace = this . replace ; } private pause ( ) { const { entityStore } = this . config ; const { clear , delete : deleteFunction , merge , replace , } = this . storeFunctions ; entityStore . clear = clear ; entityStore . delete = deleteFunction ; entityStore . merge = merge ; entityStore . replace = replace ; } }