Spaces:
Sleeping
Sleeping
| import { safe } from "ts-safe"; | |
| import { OutputSchemaSourceKey } from "./workflow.interface"; | |
| /** | |
| * Condition operators for string-based comparisons. | |
| * Used to evaluate string values from node outputs. | |
| */ | |
| export enum StringConditionOperator { | |
| Equals = "equals", | |
| NotEquals = "not_equals", | |
| Contains = "contains", | |
| NotContains = "not_contains", | |
| StartsWith = "starts_with", | |
| EndsWith = "ends_with", | |
| IsEmpty = "is_empty", | |
| IsNotEmpty = "is_not_empty", | |
| } | |
| /** | |
| * Condition operators for number-based comparisons. | |
| * Inherits string equality operators and adds numeric comparisons. | |
| */ | |
| export enum NumberConditionOperator { | |
| Equals = StringConditionOperator.Equals, | |
| NotEquals = StringConditionOperator.NotEquals, | |
| GreaterThan = "greater_than", | |
| LessThan = "less_than", | |
| GreaterThanOrEqual = "greater_than_or_equal", | |
| LessThanOrEqual = "less_than_or_equal", | |
| } | |
| /** | |
| * Condition operators for boolean value testing. | |
| */ | |
| export enum BooleanConditionOperator { | |
| IsTrue = "is_true", | |
| IsFalse = "is_false", | |
| } | |
| /** | |
| * Gets the default condition operator for a given data type. | |
| * Used when creating new conditions in the UI. | |
| */ | |
| export function getFirstConditionOperator( | |
| type: "string" | "number" | "boolean", | |
| ) { | |
| switch (type) { | |
| case "string": | |
| return StringConditionOperator.Equals; | |
| case "number": | |
| return NumberConditionOperator.Equals; | |
| case "boolean": | |
| return BooleanConditionOperator.IsTrue; | |
| default: | |
| return StringConditionOperator.Equals; | |
| } | |
| } | |
| /** | |
| * Union type of all possible condition operators. | |
| */ | |
| export type ConditionOperator = | |
| | StringConditionOperator | |
| | NumberConditionOperator | |
| | BooleanConditionOperator; | |
| /** | |
| * A single condition rule that compares a value from a node output | |
| * with a target value using a specified operator. | |
| */ | |
| export type ConditionRule = { | |
| source: OutputSchemaSourceKey; // Reference to another node's output field | |
| operator: ConditionOperator; | |
| value?: string | number | boolean; // Comparison value (not needed for is_empty, is_not_empty, is_true, is_false) | |
| }; | |
| /** | |
| * A condition branch for if-elseIf-else structure. | |
| * Each branch can have multiple conditions combined with AND/OR logic. | |
| */ | |
| export type ConditionBranch = { | |
| id: "if" | "else" | (string & {}); | |
| type: "if" | "elseIf" | "else"; | |
| conditions: ConditionRule[]; // Not needed for 'else' type | |
| logicalOperator: "AND" | "OR"; // How to combine multiple conditions, not needed for 'else' | |
| }; | |
| /** | |
| * Complete condition structure supporting if-elseIf-else branching. | |
| * Used by Condition nodes to determine execution flow. | |
| */ | |
| export type ConditionBranches = { | |
| if: ConditionBranch; | |
| elseIf?: ConditionBranch[]; // Optional multiple elseIf branches | |
| else: ConditionBranch; // Optional else branch | |
| }; | |
| /** | |
| * Evaluates a condition branch to determine if it should be executed. | |
| * | |
| * @param branch - The condition branch to evaluate | |
| * @param getSourceValue - Function to get values from node outputs | |
| * @returns True if the branch conditions are met | |
| */ | |
| export function checkConditionBranch( | |
| branch: ConditionBranch, | |
| getSourceValue: ( | |
| source: OutputSchemaSourceKey, | |
| ) => string | number | boolean | undefined, | |
| ): boolean { | |
| // Evaluate all conditions in the branch | |
| const results = branch.conditions?.map((condition) => { | |
| return checkConditionRule({ | |
| operator: condition.operator, | |
| target: String(condition.value || ""), | |
| source: getSourceValue(condition.source), | |
| }); | |
| }) ?? [false]; | |
| // Combine results based on logical operator | |
| if (branch.logicalOperator === "AND") { | |
| return results.every((result) => result); | |
| } | |
| return results.some((result) => result); | |
| } | |
| /** | |
| * Evaluates a single condition rule. | |
| * | |
| * @param params - The condition rule parameters | |
| * @returns True if the condition is met | |
| */ | |
| function checkConditionRule({ | |
| operator, | |
| target, | |
| source, | |
| }: { | |
| operator: ConditionOperator; | |
| target: string; | |
| source?: string | number | boolean; | |
| }): boolean { | |
| return safe(() => { | |
| switch (operator) { | |
| case StringConditionOperator.Equals: | |
| if (source == target) return true; | |
| break; | |
| case StringConditionOperator.NotEquals: | |
| if (source != target) return true; | |
| break; | |
| case StringConditionOperator.Contains: | |
| if (String(source).includes(String(target))) return true; | |
| break; | |
| case StringConditionOperator.NotContains: | |
| if (!String(source).includes(String(target))) return true; | |
| break; | |
| case StringConditionOperator.StartsWith: | |
| if (String(source).startsWith(String(target))) return true; | |
| break; | |
| case StringConditionOperator.EndsWith: | |
| if (String(source).endsWith(String(target))) return true; | |
| break; | |
| case StringConditionOperator.IsEmpty: | |
| if (!source) return true; | |
| break; | |
| case StringConditionOperator.IsNotEmpty: | |
| if (source) return true; | |
| break; | |
| case NumberConditionOperator.GreaterThan: | |
| if (Number(source) > Number(target)) return true; | |
| break; | |
| case NumberConditionOperator.LessThan: | |
| if (Number(source) < Number(target)) return true; | |
| break; | |
| case NumberConditionOperator.GreaterThanOrEqual: | |
| if (Number(source) >= Number(target)) return true; | |
| break; | |
| case NumberConditionOperator.LessThanOrEqual: | |
| if (Number(source) <= Number(target)) return true; | |
| break; | |
| case BooleanConditionOperator.IsTrue: | |
| if (source) return true; | |
| break; | |
| case BooleanConditionOperator.IsFalse: | |
| if (!source) return true; | |
| break; | |
| } | |
| return false; | |
| }) | |
| .ifFail((e) => { | |
| console.error("Condition evaluation error:", e); | |
| return false; | |
| }) | |
| .unwrap(); | |
| } | |