UNPKG

@flowlab/all

Version:

A cool library focusing on handling various flows

229 lines (207 loc) 7.12 kB
import { IStepConfig, StepType, INodeContext, IWorkflowContext } from '../types/index.js'; /** * MARK: - Step * @class Step * @description 代表工作流中的一个步骤实例 */ export class Step { public readonly config: IStepConfig; constructor(config: IStepConfig) { // 可以在这里添加对 config 的验证 if (!config.id) throw new Error("步骤配置必须包含 'id'"); if (!config.type) throw new Error(`步骤 "${config.id}" 必须包含 'type'`); // 设置默认值 this.config = { maxRetries: 0, retryDelay: 0, compensateOnFailure: false, ...config, }; } /** * MARK: - Getters * 获取步骤 ID */ get id(): string { return this.config.id; } /** * MARK: - Getters * 获取步骤类型 */ get type(): StepType { return this.config.type; } /** * MARK: nextStepId * 获取下一个顺序步骤的 ID */ get nextStepId(): string | undefined { return this.config.nextStepId; } /** * 评估条件 (仅用于 CONDITION 类型) * @param context - 工作流上下文 * @returns 条件评估结果 (布尔值或分支键名) * @throws 如果步骤类型不是 CONDITION 或未提供条件/分支,则抛出错误 */ evaluateCondition(context: IWorkflowContext): boolean | string { if (this.type !== StepType.CONDITION) { throw new Error(`步骤 "${this.id}" 不是条件类型,无法评估条件。`); } if (!this.config.condition) { throw new Error(`条件步骤 "${this.id}" 未定义 'condition' 函数或表达式。`); } try { const result = this.config.condition(context); if (typeof result === 'boolean') { // 如果是布尔值,通常用于决定是否执行 nextStepId return result; } else if (typeof result === 'string') { // 如果是字符串,用作分支的 key if (!this.config.branches || !this.config.branches[result]) { console.warn(`[Step: ${this.id}] 条件评估结果 "${result}" 没有对应的分支目标。`); // 可以选择抛出错误或返回一个默认行为(例如 false) // throw new Error(`条件步骤 "${this.id}" 的分支中未找到键 "${result}"。`); return false; // 或者返回一个特殊值表示无匹配分支 } return result; // 返回分支的 key } else { throw new Error(`条件步骤 "${this.id}"'condition' 函数返回了无效类型: ${typeof result}`); } } catch (error: any) { console.error(`[Step: ${this.id}] 评估条件时出错:`, error); throw new Error(`评估步骤 "${this.id}" 的条件时失败: ${error.message}`); } } /** * 获取条件分支的目标步骤 ID (仅用于 CONDITION 类型) * @param branchKey - evaluateCondition 返回的分支键名 * @returns 目标步骤 ID * @throws 如果步骤类型不是 CONDITION 或未提供分支,或找不到对应的分支键,则抛出错误 */ getBranchTarget(branchKey: string): string { if (this.type !== StepType.CONDITION) { throw new Error(`步骤 "${this.id}" 不是条件类型,无法获取分支目标。`); } if (!this.config.branches) { throw new Error(`条件步骤 "${this.id}" 未定义 'branches'。`); } const targetStepId = this.config.branches[branchKey]; if (!targetStepId) { throw new Error(`条件步骤 "${this.id}" 的分支中未找到键 "${branchKey}"。`); } return targetStepId; } /** * 获取并行步骤的配置 (仅用于 PARALLEL 类型) * @returns 并行步骤配置数组 * @throws 如果步骤类型不是 PARALLEL 或未提供并行步骤,则抛出错误 */ getParallelSteps(): IStepConfig[] { if (this.type !== StepType.PARALLEL) { throw new Error(`步骤 "${this.id}" 不是并行类型,无法获取并行步骤。`); } if (!this.config.parallelSteps || this.config.parallelSteps.length === 0) { throw new Error(`并行步骤 "${this.id}" 未定义 'parallelSteps' 或为空。`); } return this.config.parallelSteps; } /** * 获取子工作流 ID (仅用于 SUB_WORKFLOW 类型) * @returns 子工作流定义 ID * @throws 如果步骤类型不是 SUB_WORKFLOW 或未提供子工作流 ID,则抛出错误 */ getSubWorkflowId(): string { if (this.type !== StepType.SUB_WORKFLOW) { throw new Error(`步骤 "${this.id}" 不是子工作流类型。`); } if (!this.config.subWorkflowId) { throw new Error(`子工作流步骤 "${this.id}" 未定义 'subWorkflowId'。`); } return this.config.subWorkflowId; } /** * 获取传递给子工作流的输入 (仅用于 SUB_WORKFLOW 类型) */ getSubWorkflowInput(): Record<string, any> | undefined { if (this.type !== StepType.SUB_WORKFLOW) { throw new Error(`步骤 "${this.id}" 不是子工作流类型。`); } return this.config.subWorkflowInput; } /** * 获取关联的节点 ID (仅用于 TASK 类型) */ getNodeId(): string | undefined { if (this.type !== StepType.TASK) { // 对于非 TASK 类型,可能没有 nodeId // console.warn(`步骤 "${this.id}" 不是 TASK 类型,但尝试获取 nodeId。`); return undefined; } if (!this.config.nodeId) { throw new Error(`任务步骤 "${this.id}" 未定义 'nodeId'。`); } return this.config.nodeId; } /** * 获取事件名称 (仅用于 EVENT_* 类型) */ getEventName(): string { if (this.type !== StepType.EVENT_TRIGGER && this.type !== StepType.EVENT_LISTENER) { throw new Error(`步骤 "${this.id}" 不是事件类型。`); } if (!this.config.event) { throw new Error(`事件步骤 "${this.id}" 未定义 'event' 名称。`); } return this.config.event; } /** * 获取步骤的静态输入或输入映射 */ getInputConfig(): Record<string, any> | undefined { return this.config.input; } /** * 获取步骤的输出映射 */ getOutputMapping(): Record<string, string> | undefined { return this.config.outputMapping; } /** * 获取超时时间 */ getTimeout(): number | undefined { return this.config.timeout; } /** * 获取最大重试次数 */ getMaxRetries(): number { return this.config.maxRetries ?? 0; } /** * 获取重试延迟 */ getRetryDelay(): number { return this.config.retryDelay ?? 0; } /** * 获取失败补偿设置 */ getCompensateOnFailure(): boolean | string { return this.config.compensateOnFailure ?? false; } /** * 获取执行此步骤所需的角色 */ getRequiredRoles(): string[] | undefined { return this.config.requiredRoles; } /** * 获取 SLA 配置 */ getSla(): number | undefined { return this.config.sla; } }