in packages/bonito-core/src/action/action.ts [213:287]
async execute(): Promise<ActionExecutionResult> {
let executionResult: ActionExecutionResult = {
success: false,
// Default to error status in case an exception is thrown
validationStatus: new ValidationStatus(
"error",
"Failed to execute action"
),
};
try {
this._isExecuting = true;
// Store a reference to the current form values at the time validation
// was run in case they change
const formValues = this.form.values;
// Finalize will force the validation to complete, and not be
// pre-empted by a subsequent call to validate()
const snapshot = await this.form.validate({ force: true });
const validationStatus = snapshot.overallStatus;
if (!validationStatus) {
// This would indicate a bug
throw new Error(
"Form validation failed: validation status is null or undefined"
);
}
executionResult.validationStatus = validationStatus;
if (validationStatus.level === "error") {
// Validation failed - early out
this._lastExecutionResult = executionResult;
return executionResult;
}
try {
const result = await this.onExecute(formValues);
if (result) {
executionResult = result;
} else {
executionResult.success = true;
}
} catch (e) {
executionResult.error =
e ?? "Failed to execute action " + this.actionName;
executionResult.validationStatus = new ValidationStatus(
"error",
`${String(e)}`
);
this.logger.warn("Action failed to execute:", e);
}
} finally {
this._isExecuting = false;
// Always resolve rather than reject. Waiting for execution
// isn't the right place to handle errors. Instead, handle rejections
// from execute() itself.
this._executionDeferred.resolve(executionResult);
// Create a new deferred execution object since execution
// can happen again and again
this._executionDeferred = new Deferred<ActionExecutionResult>();
}
this._lastExecutionResult = executionResult;
if (!executionResult.success) {
this.form.forceValidationStatus(
this._lastExecutionResult.validationStatus
);
}
return executionResult;
}