UNPKG

execution-engine

Version:

A TypeScript library for tracing and visualizing code execution workflows.

56 lines (55 loc) 3.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.execute = execute; const functionMetadata_1 = require("../common/utils/functionMetadata"); const isAsync_1 = require("../common/utils/isAsync"); /** * Executes a given function (`blockFunction`) with the provided inputs and optional extra inputs. * Supports both synchronous and asynchronous functions, with optional success and error callbacks. * * @template INPUT - A tuple type representing the expected parameters of `blockFunction`. * @template OUTPUT - The return type of `blockFunction`, which can be either synchronous (`OUTPUT`) or a `Promise<OUTPUT>`. * @template RESPONSE - The type returned by `successCallback` (if provided), otherwise defaults to `OUTPUT`. * @template ERROR - The type returned by `errorCallback` (if provided), otherwise defaults to `RESPONSE`. * * @param blockFunction - The function to execute, which may be synchronous or asynchronous. * @param inputs - The primary set of inputs passed to `blockFunction`. Defaults to an empty tuple. * @param extraInputs - Additional arguments appended to `inputs` when calling `blockFunction`. Defaults to an empty array. * @param successCallback - An optional function that transforms the successful output of `blockFunction`. * @param errorCallback - An optional function that transforms or handles errors from `blockFunction`. * * @throws {Error} If insufficient parameters are provided to `blockFunction`, making proper tracing impossible. * * @returns Either: * - `RESPONSE` if `blockFunction` is synchronous. * - `Promise<RESPONSE>` if `blockFunction` is asynchronous. * - `ERROR` or `Promise<ERROR>` if an error occurs and `errorCallback` is provided. */ function execute(blockFunction, inputs = [], extraInputs = [], successCallback, errorCallback) { const functionParamNames = (0, functionMetadata_1.extractFunctionParamNames)(blockFunction); if (blockFunction.length > inputs.length + extraInputs.length) { const paramNames = extraInputs.length ? functionParamNames.slice(0, -extraInputs.length) : functionParamNames; throw new Error(`Could not trace your function properly if you don't provide parameters: (${paramNames})`); } if ((0, isAsync_1.isAsync)(blockFunction)) { return blockFunction .bind(this)(...inputs, ...extraInputs) .then((output) => successCallback ? successCallback.bind(this)(output, true) : output) .catch((error) => (errorCallback ? errorCallback.bind(this)(error, true) : error)); } else { let result; try { result = blockFunction.bind(this)(...inputs, ...extraInputs); } catch (error) { return errorCallback ? errorCallback.bind(this)(error, false) : error; } if (result instanceof Promise) { return result .then((output) => successCallback ? successCallback.bind(this)(output, true) : output) .catch((error) => (errorCallback ? errorCallback.bind(this)(error, true) : error)); } return successCallback ? successCallback.bind(this)(result, false) : result; } }