import { DocumentNode , FragmentDefinitionNode } from 'graphql' ; import { ApolloClient } from 'apollo-client' ; import { DataProxy } from 'apollo-cache' ; import produce from 'immer' ; import { ReceivedContext , Context } from './types/common' ; import { Action , MutationAsAction } from './types/effect' ; export function buildContext ( context , client ) { return { ... context , patchQuery : patchQuery ( client ) , patchFragment : patchFragment ( context , client ) , writeData ( options ) { return client . writeData ( options ) ; } , } ; } export function buildGetCacheKey ( cache ) { return ( obj ) => { if ( ( cache as any ) . config ) { return ( cache as any ) . config . dataIdFromObject ( obj ) ; } else { throw new Error ( 'To use context.getCacheKey, you need to use a cache that has a configurable dataIdFromObject, like apollo-cache-inmemory.' ) ; } } ; } export function getFragmentTypename ( fragment ) { const def = fragment . definitions . find ( def => def . kind === 'FragmentDefinition' ) as FragmentDefinitionNode ; return def . typeCondition . name . value ; } export function patchQuery ( client ) { return < R = any > ( query , patchFn ) : R => { const options = isDocument ( query ) ? { query } : query ; const obj = client . readQuery ( options ) ; const data = produce ( obj , patchFn ) ; client . writeQuery ( { ... options , data , } ) ; return data ; } ; } export function patchFragment ( context , client ) { return < R = any > ( fragment , obj , patchFn ) : R => { const __typename = getFragmentTypename ( fragment ) ; const id = context . getCacheKey ( { ... obj , __typename , } ) ; const frgmt = client . readFragment ( { fragment , id , } ) ; const data = produce ( frgmt , patchFn ) ; client . writeFragment ( { fragment , id , data : { ... data , __typename , } , } ) ; return data ; } ; } export function isDocument ( doc ) { return doc && doc . kind === 'Document' ; } export function isMutationAsAction ( action ) { return action . type === 'mutation' ; } export function getActionType ( action ) { if ( action . constructor && action . constructor . type ) { return action . constructor . type ; } return action . type ; }