import Callable from '../utility/Callable' ; import State from '../State' ; import { routeToPath } from '../utility' ; /** Callable type representing a function that either _reads_ or _writes_ the state at a given _path_. When invoked, returns an instance of {@linkcode State}. */ export default class Operation extends Callable { /** The _query_ representing the operation. */ query : string ; /** Determines whether the operation may be cached. */ isCacheable : boolean ; /** The _paths_ which should be invalidated whenever the operation is invoked. */ dependents : Array < string > ; /** The _paths_ upon which any {@linkcode State} instance produced by invoking the operation will depend. */ dependencies : Array < string > ; param path param func param args param isRead param isCacheable param dependents param dependencies constructor ( path , func , args , isRead , isCacheable , dependents = [ ] , dependencies = [ ] ) { super ( async ( ) => { let result ; try { result = < State > await func ( args ) ; if ( ! ( result instanceof State ) ) { console . log ( 'Unexpected result:' , result ) ; throw new Error ( 'Internal Server Error.' ) ; } } catch ( err ) { console . log ( err ) ; result = State . INTERNAL_SERVER_ERROR ( 'An error occurred.' ) ; } result . $query = this . query ; result . $dependencies . push ( ... this . dependencies ) ; return result ; } ) ; this . query = routeToPath ( path , args , true ) ; this . isCacheable = isCacheable && isRead ; this . dependents = isRead ? [ ] : [ path , ... dependents ] ; this . dependencies = isRead ? [ path , ... dependencies ] : [ ] ; } }