import { Plugin , Status } from '@tinkoff/request-core' ; import { shouldCacheExecute , getCacheKey as getCacheKeyUtil , metaTypes } from '@tinkoff/request-cache-utils' ; import { getHeader } from '@tinkoff/request-plugin-protocol-http' ; import { ETAG } from './constants' ; declare module '@tinkoff/request-core/lib/types.h' { export interface Request { etagCache ? : boolean ; etagCacheForce ? : boolean ; } } param { object } lruOptions param { boolean } shouldExecute param { function } memoryConstructor param { function } getCacheKey export default ( { lruOptions = { max : 1000 } , shouldExecute = true , memoryConstructor = ( options ) => new ( require ( 'lru-cache' ) ) ( options ) , getCacheKey = undefined , } = { } ) : Plugin => { const lruCache = memoryConstructor ( { ... lruOptions , stale : true , } ) ; return { shouldExecute : shouldCacheExecute ( 'etag' , shouldExecute ) , init : ( context , next ) => { const cacheKey = getCacheKeyUtil ( context , getCacheKey ) ; if ( lruCache . has ( cacheKey ) ) { const { key , value } = lruCache . get ( cacheKey ) ; const request = context . getRequest ( ) ; context . updateInternalMeta ( ETAG , { value , } ) ; return next ( { request : { ... request , headers : { ... request . headers , 'If-None-Match' : key , } , } , } ) ; } next ( ) ; } , complete : ( context , next ) => { const cacheKey = getCacheKeyUtil ( context , getCacheKey ) ; const etag = getHeader ( context as any , 'etag' ) ; if ( etag ) { lruCache . set ( cacheKey , { key : etag , value : context . getResponse ( ) , } ) ; } next ( ) ; } , error : ( context , next ) => { const { error } = context . getState ( ) ; if ( ( error as any ) . status === 304 ) { const { value = null } = context . getInternalMeta ( ETAG ) || { } ; if ( value ) { context . updateExternalMeta ( metaTypes . CACHE , { etagCache : true , } ) ; return next ( { status : Status . COMPLETE , response : value , } ) ; } } next ( ) ; } , } ; } ;