import { setHelperManager , helperCapabilities , createCache , getValue , setOwner , destroy , registerDestructor , associateDestroyableChild } from '../environment' ; import type { TemplateArgs , Cache } from './types' ; declare const HELPER_DEFINITION ; type HelperDefinition < T = unknown > = T & { readonly [ HELPER_DEFINITION ] : true ; } ; type Owner = object ; type Thunk = ( ... args : any [ ] ) => void ; export abstract class Resource < Args extends TemplateArgs = TemplateArgs > { protected readonly args ! : Args ; constructor ( ownerOrThunk , args ) { if ( typeof ownerOrThunk === 'function' ) { return { definition : this . constructor , args : ownerOrThunk } ; } setOwner ( this , ownerOrThunk ) ; this . args = args ; } setup ( ) { } update ? ( ) ; teardown ? ( ) ; } class ResourceManager { readonly capabilities = helperCapabilities ( '3.23' , { hasValue : true , hasDestroyable : true } ) ; private readonly owner : Owner ; constructor ( owner ) { this . owner = owner ; } createHelper < Args extends TemplateArgs = TemplateArgs > ( Class , args ) { const { update , teardown } = Class . prototype as Resource ; const hasUpdate = typeof update === 'function' ; const hasTeardown = typeof teardown === 'function' ; const owner = this . owner ; let instance ; let cache ; if ( hasUpdate ) { cache = createCache ( ( ) => { if ( instance === undefined ) { instance = setupInstance ( cache , Class , owner , args , hasTeardown ) ; } else { instance . update ! ( ) ; } return instance ; } ) ; } else { cache = createCache ( ( ) => { if ( instance !== undefined ) { destroy ( instance ) ; } instance = setupInstance ( cache , Class , owner , args , hasTeardown ) ; return instance ; } ) ; } return cache ; } getValue ( cache ) { const instance = getValue ( cache ) ; return instance ; } getDestroyable ( cache ) { return cache ; } getDebugName ( fn ) { return fn . name || '(anonymous function)' ; } } function setupInstance < T extends Resource > ( cache , Class , owner , args , hasTeardown ) { const instance = new Class ( owner , args ) ; associateDestroyableChild ( cache , instance ) ; instance . setup ( ) ; if ( hasTeardown ) { registerDestructor ( instance , ( ) => instance . teardown ! ( ) ) ; } return instance ; } setHelperManager ( ( owner ) => new ResourceManager ( owner ) , Resource ) ;