import { Command , CommandCompletion , CommandInterception , CompletionBatch , CompletionError , Model , Interceptor , Result , CommandAction } from "./types" ; import { PathMapper } from "./path-mapper" ; export function applyCompletions < T extends object , C > ( model , completions , pathMapper , intercept , context ? ) { const startUpdate = model . getCommandCount ( ) ; let modifiedBatch ; let errors ; completions . forEach ( ( c , idx ) => { let commandPath = c . command . path || [ ] ; const mapped = pathMapper . get ( commandPath ) ; let command = c . command ; if ( mapped != undefined ) { const { path , ... restOfCommand } = c . command ; command = { path : mapped , ... restOfCommand } ; } commandPath = mapped || commandPath ; const interception = intercept ? intercept ( model . getDocument ( ) , command , context ) : undefined ; let isModified = mapped != undefined || interception != undefined ; const resultWithCommand = applyCommandWithInterception ( model , command , interception , c . createdId ) ; const result = resultWithCommand . result ; if ( resultWithCommand . modifiedCommand ) { command = resultWithCommand . modifiedCommand ; } if ( result . isSuccess === true ) { if ( result . createdId != undefined && c . createdId != undefined && result . createdId !== c . createdId ) { isModified = true ; pathMapper . put ( commandPath . concat ( c . createdId ) , commandPath . concat ( result . createdId ) ) ; } if ( modifiedBatch != undefined || isModified ) { modifiedBatch = modifiedBatch || completions . slice ( 0 , idx ) ; const appliedCompletion = { command , createdId : result . createdId } ; modifiedBatch . push ( appliedCompletion ) ; } } else { modifiedBatch = modifiedBatch || completions . slice ( 0 , idx ) ; if ( errors == undefined ) { errors = [ ] ; } errors . push ( { action : c . command . action , path : commandPath , errorMessage : result . error } ) ; } } ) ; if ( modifiedBatch ) { return { applied : { from : startUpdate , completions : modifiedBatch } , errors } ; } else { return undefined ; } } export function applyCommandWithInterception < T extends object , P extends object > ( model , command , interception ? , proposedCreateId ? ) { if ( interception == undefined ) { return { result : model . apply ( command , proposedCreateId ) } ; } else if ( command . action !== CommandAction . Delete && ( interception as { newProps : any ; } ) . newProps != undefined ) { let c ; if ( command . action === CommandAction . Create ) { c = { path : command . path , action : command . action , props : ( interception as { newProps : P ; } ) . newProps } ; } else { c = { path : command . path , action : command . action , props : ( interception as { newProps : Partial < P > ; } ) . newProps } ; } return { result : model . apply ( c , proposedCreateId ) , modifiedCommand : c } ; } return { result : { isSuccess : false , error : ( interception as { rejection : string ; } ) . rejection } } ; }