import { DocumentNode , print } from 'graphql' ; import { Listener , FinchCache } from './types' ; type Cache = Map < string , unknown > ; interface ListenerMap { [ key ] : Array < Listener < unknown > > ; } interface QueryCacheOptions { hydrate ? : Cache ; } implements FinchCache export class QueryCache implements FinchCache { cache : Cache ; listeners : ListenerMap ; param doc param variables returns static serializeQuery ( doc , variables ) { return `${ print ( doc ) }:${ JSON . stringify ( variables ) }` ; } param options . hydrate constructor ( options = { } ) { this . cache = options . hydrate ?? new Map ( ) ; this . listeners = { } ; } subscribe < Query extends unknown > ( doc , variables , listener ) { const key = QueryCache . serializeQuery ( doc , variables ) ; if ( typeof this . listeners [ key ] === 'undefined' ) { this . listeners [ key ] = [ ] ; } this . listeners [ key ] . push ( listener ) ; return ( ) => { const index = this . listeners [ key ] . indexOf ( listener ) ; this . listeners [ key ] = [ ... this . listeners [ key ] . slice ( 0 , index ) , ... this . listeners [ key ] . slice ( index + 1 ) , ] ; } ; } setCache < Query extends unknown > ( doc , variables , result ) { const key = QueryCache . serializeQuery ( doc , variables ) ; this . setCacheKey < Query > ( key , result ) ; } getCache < Query extends unknown > ( doc , variables ) { const key = QueryCache . serializeQuery ( doc , variables ) ; return this . cache . get ( key ) as Query | undefined ; } private setCacheKey < Query extends unknown > ( key , value ) { const listeners = this . listeners [ key ] ?? [ ] ; this . cache . set ( key , value ) ; listeners . forEach ( fn => { fn ( value ) ; } ) ; } }