import { Log , Option , OptionType , Plugin , PluginContext , SetupResult , StorageFactory , resolveStoragePersist , } from "@miniflare/shared" ; import { Cache , InternalCacheOptions } from "./cache" ; import { CacheError } from "./error" ; import { CacheInterface } from "./helpers" ; import { NoOpCache } from "./noop" ; const DEFAULT_CACHE_NAME = "default" ; const MAX_CACHE_NAME_SIZE = 1024 ; const NOOP_CACHE = new NoOpCache ( ) ; export class CacheStorage { readonly #options : CacheOptions ; readonly #log : Log ; readonly #storage : StorageFactory ; readonly #internalOptions : InternalCacheOptions ; #warnUsage ? : boolean ; #defaultCache ? : CacheInterface ; constructor ( options , log , storageFactory , internalOptions ) { this . #options = options ; this . #log = log ; this . #storage = storageFactory ; this . #warnUsage = options . cacheWarnUsage ; this . #internalOptions = internalOptions ; } #maybeWarnUsage ( ) { if ( ! this . #warnUsage ) return ; this . #warnUsage = false ; this . #log . warn ( "Cache operations will have no impact if you deploy to a workers.dev subdomain!" ) ; } get default ( ) : CacheInterface { const defaultCache = this . #defaultCache ; if ( defaultCache ) return defaultCache ; const { cache , cachePersist } = this . #options ; if ( cache === false ) return NOOP_CACHE ; this . #maybeWarnUsage ( ) ; return ( this . #defaultCache = new Cache ( this . #storage . storage ( DEFAULT_CACHE_NAME , cachePersist ) , this . #internalOptions ) ) ; } async open ( cacheName ) { if ( cacheName === DEFAULT_CACHE_NAME ) { throw new CacheError ( "ERR_RESERVED" , `\"${ cacheName }\" is a reserved cache name` ) ; } if ( cacheName . length > MAX_CACHE_NAME_SIZE ) { throw new TypeError ( "Cache name is too long." ) ; } const { cache , cachePersist } = this . #options ; if ( cache === false ) return NOOP_CACHE ; this . #maybeWarnUsage ( ) ; return new Cache ( await this . #storage . storage ( cacheName , cachePersist ) , this . #internalOptions ) ; } } export interface CacheOptions { cache ? : boolean ; cachePersist ? : boolean | string ; cacheWarnUsage ? : boolean ; } export class CachePlugin extends Plugin < CacheOptions > implements CacheOptions { @ Option ( { type : OptionType . BOOLEAN , description : "Enable default/named caches (enabled by default)" , negatable : true , logName : "Cache" , fromWrangler : ( { miniflare } ) => miniflare ?. cache , } ) cache ? : boolean ; @ Option ( { type : OptionType . BOOLEAN_STRING , description : "Persist cached data (to optional path)" , logName : "Cache Persistence" , fromWrangler : ( { miniflare } ) => miniflare ?. cache_persist , } ) cachePersist ? : boolean | string ; @ Option ( { type : OptionType . NONE , fromWrangler : ( { workers_dev } ) => workers_dev , } ) cacheWarnUsage ? : boolean ; #unblockedCaches ? : CacheStorage ; constructor ( ctx , options ? ) { super ( ctx ) ; this . assignOptions ( options ) ; } setup ( storageFactory ) { const persist = resolveStoragePersist ( this . ctx . rootPath , this . cachePersist ) ; const options = { cache : this . cache , cachePersist : persist , cacheWarnUsage : this . cacheWarnUsage , } ; const files = this . ctx . compat . isEnabled ( "formdata_parser_supports_files" ) ; const blockGlobalAsyncIO = ! this . ctx . globalAsyncIO ; const caches = new CacheStorage ( options , this . ctx . log , storageFactory , { formDataFiles : files , blockGlobalAsyncIO , } ) ; this . #unblockedCaches = blockGlobalAsyncIO ? new CacheStorage ( options , this . ctx . log , storageFactory , { formDataFiles : files , blockGlobalAsyncIO : false , } ) : caches ; return { globals : { caches } } ; } getCaches ( ) { return this . #unblockedCaches ! ; } }