import { EventObject , Machine , Event , StateNodeConfig , StateSchema , } from 'xstate' ; import { AnyEventObject , MachineOptions , StateMachine } from 'xstate/lib/types' ; import { FormLoader , FormText , StaticText } from './Form' ; import { Application , ActionCardTag } from './Application' ; export type ApplicationRole = 'applicant' | 'assignee' | string ; export enum DefaultEvents { PAYMENT = 'PAYMENT' , APPROVE = 'APPROVE' , ASSIGN = 'ASSIGN' , REJECT = 'REJECT' , SUBMIT = 'SUBMIT' , ABORT = 'ABORT' , EDIT = 'EDIT' } export type ReadWriteValues = 'all' | { answers ? : string [ ] ; externalData ? : string [ ] ; } ; export interface RoleInState < T extends EventObject = AnyEventObject > { id : ApplicationRole ; read ? : ReadWriteValues ; write ? : ReadWriteValues ; formLoader ? : FormLoader ; actions ? : CallToAction < T > [ ] ; } export interface ApplicationContext { application : Application ; } export type CallToAction < T extends EventObject = AnyEventObject > = { event : Event < T > | string ; name : FormText ; type : 'primary' | 'subtle' | 'reject' | 'sign' ; } ; export interface ApplicationTemplateAPIAction { apiModuleAction : string ; shouldPersistToExternalData ? : boolean ; externalDataId ? : string ; throwOnError ? : boolean ; } export type StateLifeCycle = { shouldBeListed : boolean ; shouldBePruned : false ; } | { shouldBeListed : boolean ; shouldBePruned : true ; whenToPrune : number | ( ( application : Application ) => Date ) ; } ; export interface ApplicationStateMeta < T extends EventObject = AnyEventObject > { name : string ; lifecycle : StateLifeCycle ; actionCard ? : { title ? : StaticText ; description ? : StaticText ; tag ? : { label ? : StaticText ; variant ? : ActionCardTag ; } ; } ; progress ? : number ; roles ? : RoleInState < T > [ ] ; onExit ? : ApplicationTemplateAPIAction ; onEntry ? : ApplicationTemplateAPIAction ; } export interface ApplicationStateSchema < T extends EventObject = AnyEventObject > extends StateSchema { meta : ApplicationStateMeta < T > ; states : { [ key ] : ApplicationStateSchema < T > ; } ; } export type ApplicationStateMachine < TContext extends ApplicationContext , TStateSchema extends ApplicationStateSchema < TEvents > , TEvents extends EventObject > = StateMachine < TContext , TStateSchema , TEvents > ; export function createApplicationMachine < TContext extends ApplicationContext , TStateSchema extends ApplicationStateSchema < TEvent > , TEvent extends EventObject = AnyEventObject > ( application , config , options ? , initialContext ? ) { const context = initialContext ? { ... initialContext , application } : { application } ; const applicationState = application . state ; let initialState = config . initial ; if ( config ?. states && config . states [ applicationState ] ) { initialState = applicationState ; } return Machine ( { ... config , initial : initialState } , options ?? { } , context as TContext ) ; }