import { get as consumeTag } from '@ember/object' ; import { LifecycleResource } from './lifecycle' ; export type TaskReturnType < T > = T extends TaskIsh < any , infer Return > ? Return : unknown ; export type TaskArgsType < T > = T extends TaskIsh < infer Args , any > ? Args : unknown [ ] ; export interface TaskIsh < Args extends any [ ] , Return > { perform : ( ... args : Args ) => TaskInstance < Return > ; cancelAll : ( ) => void ; } private export interface TaskInstance < Return = unknown > extends Promise < Return > { readonly value : Return | null ; readonly error : unknown ; readonly isSuccessful : boolean ; readonly isError : boolean ; readonly isCanceled : boolean ; readonly hasStarted : boolean ; readonly isFinished : boolean ; readonly isRunning : boolean ; readonly isDropped : boolean ; cancel ( reason ? ) : void | Promise < void > ; } export const TASK = Symbol ( 'TASK' ) ; export class TaskResource < Args extends any [ ] , Return , LocalTask extends TaskIsh < Args , Return > > extends LifecycleResource < { positional : Args ; } > { declare [ TASK ] : LocalTask ; declare currentTask : TaskInstance < Return > ; declare lastTask : TaskInstance < Return > | undefined ; get taskArgs ( ) { return this . args . positional ; } get value ( ) { consumeTag ( this . currentTask , 'isRunning' ) ; return this . currentTask . value ?? this . lastTask ?. value ; } setup ( ) { this . update ( ) ; } update ( ) { if ( this . currentTask ) { this . lastTask = this . currentTask ; } this . currentTask = this [ TASK ] . perform ( ... this . taskArgs ) ; } teardown ( ) { this [ TASK ] . cancelAll ( ) ; } }