async execute()

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;
    }