UNPKG

@liyown/flow-engine

Version:

一个基于JavaScript的无状态工作流引擎框架,支持可视化拖拽、DSL定义、断点继续、自动重试等高级功能

1,437 lines (1,436 loc) 48.3 kB
import { EventEmitter as $ } from "events"; import { v4 as v } from "uuid"; class S { static createWorkflow(e) { var t, r, s, i; return { id: e.id || this.generateId(), name: e.name || "", version: e.version || "1.0.0", description: e.description, // 全局配置 global: { timeout: ((t = e.global) == null ? void 0 : t.timeout) || 3e4, retryPolicy: ((r = e.global) == null ? void 0 : r.retryPolicy) || { maxRetries: 3, delay: 1e3 }, context: ((s = e.global) == null ? void 0 : s.context) || {}, variables: ((i = e.global) == null ? void 0 : i.variables) || {} }, // 输入输出Schema input: e.input || { type: "object", properties: {} }, output: e.output || { type: "object", properties: {} }, // 步骤定义 steps: e.steps || [], // 依赖关系 dependencies: e.dependencies || [], // 条件分支 conditions: e.conditions || [], // 错误处理 errorHandlers: e.errorHandlers || [], // 元数据 metadata: e.metadata || {} }; } static generateId() { return `workflow_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; } } class j { constructor(e) { this.id = e.id, this.name = e.name, this.type = e.type, this.handler = e.handler, this.input = e.input || { type: "object" }, this.output = e.output || { type: "object" }, this.inputMapping = e.inputMapping || {}, this.retry = e.retry || { maxRetries: 0, delay: 1e3 }, this.timeout = e.timeout || 1e4, this.condition = e.condition, this.dependsOn = e.dependsOn || [], this.parallel = e.parallel || !1, this.loop = e.loop, this.onError = e.onError || "throw", this.metadata = e.metadata || {}; } } class g { constructor(e, t = {}) { this.workflowId = e, this.executionId = this.generateExecutionId(), this.startTime = Date.now(), this.status = "running", this.globalContext = {}, this.stepResults = /* @__PURE__ */ new Map(), this.variables = /* @__PURE__ */ new Map(), this.initialData = t, this.currentStep = null, this.completedSteps = /* @__PURE__ */ new Set(), this.failedSteps = /* @__PURE__ */ new Set(), this.skippedSteps = /* @__PURE__ */ new Set(), this.errors = [], this.executionHistory = [], this.breakpoints = /* @__PURE__ */ new Set(), this.isPaused = !1; } generateExecutionId() { return `exec_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; } setStepResult(e, t) { this.stepResults.set(e, { result: t, timestamp: Date.now(), executionTime: Date.now() - this.startTime }); } getStepResult(e) { return this.stepResults.get(e); } addHistoryRecord(e) { this.executionHistory.push({ ...e, timestamp: Date.now() }); } serialize() { return { workflowId: this.workflowId, executionId: this.executionId, startTime: this.startTime, endTime: this.endTime, status: this.status, globalContext: this.globalContext, stepResults: Object.fromEntries(this.stepResults), variables: Object.fromEntries(this.variables), initialData: this.initialData, currentStep: this.currentStep, completedSteps: Array.from(this.completedSteps), failedSteps: Array.from(this.failedSteps), skippedSteps: Array.from(this.skippedSteps), errors: this.errors, executionHistory: this.executionHistory, breakpoints: Array.from(this.breakpoints), isPaused: this.isPaused }; } static deserialize(e) { const t = new g(e.workflowId, e.initialData); return t.executionId = e.executionId, t.startTime = e.startTime, t.endTime = e.endTime, t.status = e.status, t.globalContext = e.globalContext, t.initialData = e.initialData, t.currentStep = e.currentStep, t.errors = e.errors, t.executionHistory = e.executionHistory, t.isPaused = e.isPaused, t.stepResults = new Map(Object.entries(e.stepResults)), t.variables = new Map(Object.entries(e.variables)), t.completedSteps = new Set(e.completedSteps), t.failedSteps = new Set(e.failedSteps), t.skippedSteps = new Set(e.skippedSteps), t.breakpoints = new Set(e.breakpoints), t; } } class y { /** * 执行节点处理器 */ async execute(e, t) { return this.handler(e, t); } /** * 获取节点元数据 */ getMetadata() { return this.metadata; } } class A extends y { constructor() { super(...arguments), this.name = "http", this.handler = async (e, t) => { const { url: r, method: s = "GET", headers: i = {}, body: n } = e; try { return await (await fetch(r, { method: s, headers: { "Content-Type": "application/json", ...i }, body: n ? JSON.stringify(n) : void 0 })).json(); } catch (o) { throw new Error(`HTTP request failed: ${o.message}`); } }, this.metadata = { name: this.name, description: "发送HTTP请求到外部API", category: "网络", displayName: "HTTP请求", inputSchema: { type: "object", properties: { url: { type: "string", format: "uri", description: "请求的目标URL" }, method: { type: "string", enum: ["GET", "POST", "PUT", "DELETE", "PATCH"], default: "GET", description: "HTTP请求方法" }, headers: { type: "object", additionalProperties: { type: "string" }, description: "HTTP请求头" }, body: { type: "object", description: "请求体(用于POST, PUT, PATCH等方法)" } }, required: ["url"] }, outputSchema: { type: "object", description: "HTTP请求的响应数据" }, examples: [ { name: "获取用户数据", input: { url: "https://api.example.com/users/1", method: "GET" } } ] }; } } class N { /** * 将数据转换为符合目标Schema的格式 * @param value 要转换的数据 * @param targetSchema 目标Schema * @returns 转换结果 */ static convert(e, t) { const r = []; let s = e; try { if (e === null) return Array.isArray(t.type) && t.type.includes("null") ? { success: !0, value: null, errors: [] } : t.type === "null" ? { success: !0, value: null, errors: [] } : (r.push(`无法将null转换为 ${t.type}`), { success: !1, value: e, errors: r }); if (e === void 0) return t.default !== void 0 ? { success: !0, value: t.default, errors: [] } : (r.push(`无法将undefined转换为 ${t.type}`), { success: !1, value: e, errors: r }); const i = Array.isArray(t.type) ? t.type.filter((n) => n !== "null")[0] || t.type[0] : t.type; switch (i) { case "string": s = this.convertToString(e, r); break; case "number": s = this.convertToNumber(e, r); break; case "integer": s = this.convertToInteger(e, r); break; case "boolean": s = this.convertToBoolean(e, r); break; case "array": s = this.convertToArray(e, t, r); break; case "object": s = this.convertToObject(e, t, r); break; case "date": case "datetime": s = this.convertToDate(e, r); break; default: return r.push(`不支持转换到类型: ${i}`), { success: !1, value: e, errors: r }; } return i === "integer" && typeof e == "number" && !Number.isInteger(e) && (r.length = 0), r.length > 0 ? { success: !1, value: e, errors: r } : { success: !0, value: s, errors: [] }; } catch (i) { return r.push(`转换过程中出错: ${i instanceof Error ? i.message : String(i)}`), { success: !1, value: e, errors: r }; } } /** * 转换为字符串 */ static convertToString(e, t) { if (typeof e == "string") return e; if (e == null) return t.push("无法将null或undefined转换为字符串"), ""; if (typeof e == "object") try { return JSON.stringify(e); } catch (r) { return t.push(`无法将对象转换为JSON字符串: ${r instanceof Error ? r.message : String(r)}`), String(e); } return String(e); } /** * 转换为数字 */ static convertToNumber(e, t) { if (typeof e == "number") return e; if (typeof e == "string") { const r = Number(e); return isNaN(r) ? (t.push(`无法将字符串 "${e}" 转换为数字`), 0) : r; } return typeof e == "boolean" ? e ? 1 : 0 : e instanceof Date ? e.getTime() : (t.push(`无法将类型 ${typeof e} 转换为数字`), 0); } /** * 转换为整数 */ static convertToInteger(e, t) { if (typeof e == "number" && Number.isInteger(e)) return e; let r = e; if (typeof e != "number" && (r = this.convertToNumber(e, t)), t.length > 0) return 0; const s = Math.trunc(r); return s !== r && typeof e == "number" && console.warn(`数字 ${r} 被截断为整数 ${s}`), s; } /** * 转换为布尔值 */ static convertToBoolean(e, t) { if (typeof e == "boolean") return e; if (typeof e == "string") { const r = e.toLowerCase().trim(); return ["true", "yes", "1", "on"].includes(r) ? !0 : (["false", "no", "0", "off"].includes(r) || t.push(`无法将字符串 "${e}" 转换为布尔值`), !1); } return typeof e == "number" ? e !== 0 : (t.push(`无法将类型 ${typeof e} 转换为布尔值`), !1); } /** * 转换为数组 */ static convertToArray(e, t, r) { if (Array.isArray(e)) return e; if (typeof e == "string") try { const s = JSON.parse(e); if (Array.isArray(s)) return s; } catch { return e.split(",").map((s) => s.trim()); } return [e]; } /** * 转换为对象 */ static convertToObject(e, t, r) { if (typeof e == "object" && e !== null && !Array.isArray(e)) return e; if (typeof e == "string") try { const s = JSON.parse(e); return typeof s == "object" && s !== null && !Array.isArray(s) ? s : (r.push(`解析的JSON不是对象: ${e}`), {}); } catch (s) { return r.push(`无法将字符串解析为JSON对象: ${s instanceof Error ? s.message : String(s)}`), {}; } if (Array.isArray(e)) try { const s = {}; for (let i = 0; i < e.length; i += 2) if (i + 1 < e.length) { const n = String(e[i]); s[n] = e[i + 1]; } return s; } catch (s) { return r.push(`无法将数组转换为对象: ${s instanceof Error ? s.message : String(s)}`), {}; } return r.push(`无法将类型 ${typeof e} 转换为对象`), {}; } /** * 转换为日期 */ static convertToDate(e, t) { if (e instanceof Date) return e; if (typeof e == "string") { const r = new Date(e); return isNaN(r.getTime()) ? (t.push(`无法将字符串 "${e}" 解析为日期`), /* @__PURE__ */ new Date()) : r; } if (typeof e == "number") { const r = new Date(e); return isNaN(r.getTime()) ? (t.push(`无法将数字 ${e} 转换为日期`), /* @__PURE__ */ new Date()) : r; } return t.push(`无法将类型 ${typeof e} 转换为日期`), /* @__PURE__ */ new Date(); } } class k { /** * 验证数据是否符合Schema * @param data 要验证的数据 * @param schema Schema定义 * @returns 验证结果 */ static validate(e, t) { const r = []; try { if (!this.validateType(e, t.type)) return r.push(`类型不匹配: 期望 ${t.type},实际为 ${typeof e}`), { valid: !1, errors: r }; switch (this.getPrimaryType(t.type)) { case "string": this.validateString(e, t, r); break; case "number": case "integer": this.validateNumber(e, t, r); break; case "boolean": break; case "array": this.validateArray(e, t, r); break; case "object": this.validateObject(e, t, r); break; case "date": case "datetime": this.validateDate(e, t, r); break; } t.enum && !t.enum.includes(e) && r.push(`值 ${e} 不在允许的枚举值 [${t.enum.join(", ")}] 中`); } catch (s) { r.push(`验证过程中出错: ${s instanceof Error ? s.message : String(s)}`); } return { valid: r.length === 0, errors: r }; } /** * 获取主要类型(如果是类型数组,返回第一个非null类型) */ static getPrimaryType(e) { if (Array.isArray(e)) { const t = e.filter((r) => r !== "null"); return t.length > 0 ? t[0] : e[0]; } return e; } /** * 验证类型是否匹配 */ static validateType(e, t) { if (e === null) return Array.isArray(t) && t.includes("null"); const r = typeof e; if (Array.isArray(e) && (t === "array" || Array.isArray(t) && t.includes("array")) || (e instanceof Date || typeof e == "string" && !isNaN(Date.parse(e))) && (t === "date" || t === "datetime" || Array.isArray(t) && (t.includes("date") || t.includes("datetime")))) return !0; if (r === "number") { if (t === "number" || t === "integer") return !(t === "integer" && !Number.isInteger(e)); if (Array.isArray(t) && (t.includes("number") || t.includes("integer"))) return t.includes("integer") && !Number.isInteger(e) ? t.includes("number") : !0; } return Array.isArray(t) ? t.some((s) => this.matchType(r, s)) : this.matchType(r, t); } /** * 匹配JavaScript类型和Schema类型 */ static matchType(e, t) { switch (t) { case "string": return e === "string"; case "number": return e === "number"; case "integer": return e === "number"; case "boolean": return e === "boolean"; case "object": return e === "object" && !Array.isArray(e); case "array": return Array.isArray(e); default: return !1; } } /** * 验证字符串 */ static validateString(e, t, r) { if (t.minLength !== void 0 && e.length < t.minLength && r.push(`字符串长度 ${e.length} 小于最小长度 ${t.minLength}`), t.maxLength !== void 0 && e.length > t.maxLength && r.push(`字符串长度 ${e.length} 大于最大长度 ${t.maxLength}`), t.pattern) try { new RegExp(t.pattern).test(e) || r.push(`字符串不匹配模式 ${t.pattern}`); } catch { r.push(`无效的正则表达式模式: ${t.pattern}`); } if (t.format) switch (t.format) { case "email": /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e) || r.push("值不是有效的电子邮件格式"); break; case "uri": try { new URL(e); } catch { r.push("值不是有效的URI格式"); } break; } } /** * 验证数字 */ static validateNumber(e, t, r) { t.type === "integer" && !Number.isInteger(e) && r.push(`值 ${e} 不是整数`), t.multipleOf !== void 0 && e % t.multipleOf !== 0 && r.push(`值 ${e} 不是 ${t.multipleOf} 的倍数`), t.maximum !== void 0 && e > t.maximum && r.push(`值 ${e} 大于最大值 ${t.maximum}`), t.exclusiveMaximum !== void 0 && e >= t.exclusiveMaximum && r.push(`值 ${e} 大于或等于独占最大值 ${t.exclusiveMaximum}`), t.minimum !== void 0 && e < t.minimum && r.push(`值 ${e} 小于最小值 ${t.minimum}`), t.exclusiveMinimum !== void 0 && e <= t.exclusiveMinimum && r.push(`值 ${e} 小于或等于独占最小值 ${t.exclusiveMinimum}`); } /** * 验证数组 */ static validateArray(e, t, r) { if (t.minItems !== void 0 && e.length < t.minItems && r.push(`数组长度 ${e.length} 小于最小长度 ${t.minItems}`), t.maxItems !== void 0 && e.length > t.maxItems && r.push(`数组长度 ${e.length} 大于最大长度 ${t.maxItems}`), t.uniqueItems && new Set(e).size !== e.length && r.push("数组包含重复项,但要求唯一项"), t.items) if (Array.isArray(t.items)) { for (let s = 0; s < Math.min(e.length, t.items.length); s++) { const i = t.items[s], n = this.validate(e[s], i); n.valid || r.push(`数组索引 ${s} 验证失败: ${n.errors.join(", ")}`); } if (e.length > t.items.length && t.additionalItems === !1) r.push("数组包含额外项,但不允许额外项"); else if (e.length > t.items.length && typeof t.additionalItems == "object") for (let s = t.items.length; s < e.length; s++) { const i = this.validate(e[s], t.additionalItems); i.valid || r.push(`额外数组项索引 ${s} 验证失败: ${i.errors.join(", ")}`); } } else for (let s = 0; s < e.length; s++) { const i = this.validate(e[s], t.items); i.valid || r.push(`数组索引 ${s} 验证失败: ${i.errors.join(", ")}`); } } /** * 验证对象 */ static validateObject(e, t, r) { const s = Object.keys(e); if (t.required) for (const i of t.required) i in e || r.push(`缺少必需属性: ${i}`); if (t.minProperties !== void 0 && s.length < t.minProperties && r.push(`对象属性数量 ${s.length} 小于最小数量 ${t.minProperties}`), t.maxProperties !== void 0 && s.length > t.maxProperties && r.push(`对象属性数量 ${s.length} 大于最大数量 ${t.maxProperties}`), t.properties) { for (const [i, n] of Object.entries(t.properties)) if (i in e) { const o = this.validate(e[i], n); o.valid || r.push(`属性 "${i}" 验证失败: ${o.errors.join(", ")}`); } } if (t.additionalProperties === !1) { const i = t.properties ? Object.keys(t.properties) : [], n = s.filter((o) => !i.includes(o)); n.length > 0 && r.push(`对象包含额外属性: ${n.join(", ")}`); } else if (typeof t.additionalProperties == "object") { const i = t.properties ? Object.keys(t.properties) : [], n = s.filter((o) => !i.includes(o)); for (const o of n) { const u = this.validate(e[o], t.additionalProperties); u.valid || r.push(`额外属性 "${o}" 验证失败: ${u.errors.join(", ")}`); } } } /** * 验证日期 */ static validateDate(e, t, r) { if (e instanceof Date) return; if (typeof e == "string") try { const i = new Date(e); if (!isNaN(i.getTime())) return; } catch { } if (typeof e != "string" || isNaN(Date.parse(String(e)))) { r.push(`值 ${e} 不是有效的日期`); return; } const s = new Date(String(e)); if (t.minimum !== void 0) { const i = new Date(t.minimum); s < i && r.push(`日期早于最小日期 ${i.toISOString()}`); } if (t.maximum !== void 0) { const i = new Date(t.maximum); s > i && r.push(`日期晚于最大日期 ${i.toISOString()}`); } } } class O extends y { constructor() { super(...arguments), this.name = "typeConvert", this.handler = async (e, t) => { const { value: r, targetSchema: s, validateAfterConversion: i = !0, throwOnError: n = !1 } = e; if (!s) throw new Error("缺少必需参数: targetSchema"); const o = N.convert(r, s); if (!o.success && n) throw new Error(`类型转换失败: ${o.errors.join("; ")}`); let u = { valid: !0, errors: [] }; if (i && o.success && (u = k.validate(o.value, s), !u.valid && n)) throw new Error(`类型验证失败: ${u.errors.join("; ")}`); return { originalValue: r, convertedValue: o.value, conversionSuccess: o.success, conversionErrors: o.errors, validationSuccess: u.valid, validationErrors: u.errors, isValid: o.success && u.valid }; }, this.metadata = { name: this.name, description: "将数据转换为指定的类型并验证", category: "数据处理", displayName: "类型转换", inputSchema: { type: "object", properties: { value: { description: "要转换的值", type: ["string", "number", "boolean", "object", "array", "null"] }, targetSchema: { type: "object", description: "目标Schema定义" }, validateAfterConversion: { type: "boolean", description: "是否在转换后验证", default: !0 }, throwOnError: { type: "boolean", description: "转换或验证失败时是否抛出错误", default: !1 } }, required: ["value", "targetSchema"] }, outputSchema: { type: "object", properties: { originalValue: { description: "原始值", type: ["string", "number", "boolean", "object", "array", "null"] }, convertedValue: { description: "转换后的值", type: ["string", "number", "boolean", "object", "array", "null"] }, conversionSuccess: { type: "boolean", description: "转换是否成功" }, conversionErrors: { type: "array", items: { type: "string" }, description: "转换错误列表" }, validationSuccess: { type: "boolean", description: "验证是否成功" }, validationErrors: { type: "array", items: { type: "string" }, description: "验证错误列表" }, isValid: { type: "boolean", description: "转换和验证是否都成功" } } }, examples: [ { name: "将字符串转换为数字", input: { value: "123", targetSchema: { type: "number" } } }, { name: "将字符串转换为日期", input: { value: "2023-01-01", targetSchema: { type: "date" } } } ] }; } } class T extends y { constructor() { super(...arguments), this.name = "delay", this.handler = async (e) => { const { duration: t = 1e3 } = e; return await new Promise((r) => setTimeout(r, t)), { delayed: !0, duration: t }; }, this.metadata = { name: this.name, description: "延迟执行指定的毫秒数", category: "工具", displayName: "延迟", inputSchema: { type: "object", properties: { duration: { type: "number", description: "延迟时间(毫秒)", default: 1e3 } } }, outputSchema: { type: "object", properties: { delayed: { type: "boolean" }, duration: { type: "number" } } } }; } } class P extends y { constructor() { super(...arguments), this.name = "log", this.handler = async (e) => { const { message: t, level: r = "info", data: s } = e; switch (r) { case "error": console.error(t, s); break; case "warn": console.warn(t, s); break; case "debug": console.debug(t, s); break; case "info": default: console.info(t, s); } return { logged: !0, timestamp: Date.now() }; }, this.metadata = { name: this.name, description: "记录日志信息", category: "工具", displayName: "日志", inputSchema: { type: "object", properties: { message: { type: "string", description: "日志消息" }, level: { type: "string", enum: ["info", "warn", "error", "debug"], default: "info", description: "日志级别" }, data: { type: "object", description: "附加数据" } }, required: ["message"] }, outputSchema: { type: "object", properties: { logged: { type: "boolean" }, timestamp: { type: "number" } } } }; } } class D extends y { constructor() { super(...arguments), this.name = "noop", this.handler = async () => ({ executed: !0 }), this.metadata = { name: this.name, description: "不执行任何操作的处理器", category: "工具", displayName: "空操作", inputSchema: { type: "object" }, outputSchema: { type: "object", properties: { executed: { type: "boolean" } } } }; } } function R() { return [ new A(), new O(), new T(), new P(), new D() ]; } class I { constructor() { this.handlers = /* @__PURE__ */ new Map(), this.metadata = /* @__PURE__ */ new Map(), this.registerBuiltinHandlers(); } /** * 注册步骤处理器 */ register(e, t, r) { this.handlers.set(e, t), r && this.registerMetadata(e, { name: e, description: r.description || `Handler for ${e}`, inputSchema: r.inputSchema || { type: "object", properties: {} }, outputSchema: r.outputSchema || { type: "object", properties: {} }, category: r.category, icon: r.icon, displayName: r.displayName || e, examples: r.examples || [] }); } /** * 注册处理器元数据 */ registerMetadata(e, t) { this.metadata.set(e, t); } /** * 获取处理器元数据 */ getMetadata(e) { return this.metadata.get(e); } /** * 获取所有处理器元数据 */ getAllMetadata() { return Array.from(this.metadata.values()); } /** * 获取步骤处理器 */ get(e) { return this.handlers.get(e); } /** * 检查处理器是否存在 */ has(e) { return this.handlers.has(e); } /** * 注册内置处理器 */ registerBuiltinHandlers() { const e = R(); for (const t of e) this.register(t.name, async (r, s) => await t.execute(r, s), t.metadata); } /** * 执行处理器 */ async executeHandler(e, t, r) { const s = this.get(e); if (!s) throw new Error(`Handler not found: ${e}`); return await s(t, r); } } class m { static mapInput(e, t, r) { if (!t || Object.keys(t).length === 0) return e; const s = {}; for (const [i, n] of Object.entries(t)) s[i] = this.evaluateExpression(n, { input: e, context: r.globalContext, variables: Object.fromEntries(r.variables), stepResults: this.mapToObject(r.stepResults) }); return s; } static evaluateExpression(e, t) { return typeof e == "string" ? e.startsWith("$") ? this.evaluateJSONPath(e, t) : e : typeof e == "object" && e !== null ? this.evaluateComplexExpression(e, t) : e; } static evaluateJSONPath(e, t) { const r = e.substring(1), s = this.getNestedValue(t, r); return s === void 0 && console.warn(`在作用域中未找到路径: ${e}`), s; } static evaluateComplexExpression(e, t) { return e.type === "concat" ? e.values.map((r) => this.evaluateExpression(r, t)).join(e.separator || "") : e.type === "template" ? this.evaluateTemplate(e.template, t) : e.type === "function" ? this.evaluateFunction(e.name, e.args, t) : e; } static evaluateTemplate(e, t) { return e.replace(/\{\{([^}]+)\}\}/g, (r, s) => { const i = this.getNestedValue(t, s.trim()); return i !== void 0 ? String(i) : r; }); } static evaluateFunction(e, t, r) { var i; const s = t.map((n) => this.evaluateExpression(n, r)); switch (e) { case "now": return Date.now(); case "uuid": return this.generateUUID(); case "length": return s[0] === void 0 || s[0] === null ? 0 : typeof s[0] != "string" && !Array.isArray(s[0]) ? (console.warn(`函数 "length" 的参数必须是字符串或数组,但收到: ${typeof s[0]}`), 0) : ((i = s[0]) == null ? void 0 : i.length) || 0; case "upper": return typeof s[0] != "string" ? (console.warn(`函数 "upper" 的参数必须是字符串,但收到: ${typeof s[0]}`), String(s[0])) : String(s[0]).toUpperCase(); case "lower": return typeof s[0] != "string" ? (console.warn(`函数 "lower" 的参数必须是字符串,但收到: ${typeof s[0]}`), String(s[0])) : String(s[0]).toLowerCase(); case "sum": return Array.isArray(s[0]) ? s[0].reduce((n, o) => { const u = Number(o); return isNaN(u) ? (console.warn(`函数 "sum" 在累加时遇到非数字值: ${o}`), n) : n + u; }, 0) : s.reduce((n, o) => { const u = Number(o); return isNaN(u) ? (console.warn(`函数 "sum" 在累加时遇到非数字值: ${o}`), n) : n + u; }, 0); default: throw new Error(`未知函数: ${e}`); } } static getNestedValue(e, t) { const r = t.split(".").reduce((s, i) => { if (!(s == null || typeof s != "object")) return s[i]; }, e); return r !== void 0 && console.log(`DataMapper: 获取路径 ${t} 的值 ${r},类型为 ${typeof r}`), r; } static mapToObject(e) { const t = {}; for (const [r, s] of e.entries()) t[r] = s; return t; } static generateUUID() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(e) { const t = Math.random() * 16 | 0; return (e === "x" ? t : t & 3 | 8).toString(16); }); } } class C { static evaluate(e, t) { return e ? typeof e == "string" ? this.evaluateExpression(e, t) : typeof e == "object" ? this.evaluateConditionObject(e, t) : !!e : !0; } static evaluateExpression(e, t) { const r = { context: t.globalContext, variables: Object.fromEntries(t.variables), stepResults: m.mapToObject(t.stepResults) }; try { return this.safeEval(e, r); } catch (s) { return console.warn("Condition evaluation failed:", s), !1; } } static evaluateConditionObject(e, t) { const { operator: r, left: s, right: i, conditions: n } = e; switch (r) { case "and": return (n == null ? void 0 : n.every((o) => this.evaluate(o, t))) ?? !1; case "or": return (n == null ? void 0 : n.some((o) => this.evaluate(o, t))) ?? !1; case "not": return !this.evaluate(n == null ? void 0 : n[0], t); case "eq": return this.getValue(s, t) === this.getValue(i, t); case "ne": return this.getValue(s, t) !== this.getValue(i, t); case "gt": return this.getValue(s, t) > this.getValue(i, t); case "gte": return this.getValue(s, t) >= this.getValue(i, t); case "lt": return this.getValue(s, t) < this.getValue(i, t); case "lte": return this.getValue(s, t) <= this.getValue(i, t); case "contains": return String(this.getValue(s, t)).includes(String(this.getValue(i, t))); case "in": { const o = this.getValue(i, t); return Array.isArray(o) && o.includes(this.getValue(s, t)); } default: return console.warn(`未知的条件操作符: ${r}`), !1; } } static getValue(e, t) { return typeof e == "string" && e.startsWith("$") ? m.evaluateExpression(e, { context: t.globalContext, variables: Object.fromEntries(t.variables), stepResults: m.mapToObject(t.stepResults) }) : e; } static safeEval(e, t) { const r = e.replace(/\$(\w+\.?\w*)/g, (s, i) => JSON.stringify(m.getNestedValue(t, i))); try { return new Function("scope", `return Boolean(${r})`)(t); } catch (s) { return console.error(`在 safeEval 中执行表达式 "${e}" (清理后为 "${r}") 时出错:`, s), !1; } } } class J { constructor(e = {}) { this.handlerRegistry = new I(), this.executionStore = e.executionStore || /* @__PURE__ */ new Map(), this.eventEmitter = e.eventEmitter || new $(), this.config = { maxConcurrentExecutions: e.maxConcurrentExecutions || 10, defaultTimeout: e.defaultTimeout || 3e4, enableBreakpoints: e.enableBreakpoints || !1, persistExecution: e.persistExecution || !1 }; } /** * 注册步骤处理器 */ registerHandler(e, t, r) { this.handlerRegistry.register(e, async (s, i) => await t(s, i), r); } /** * 执行工作流 */ async execute(e, t = {}, r = {}) { var n; const s = "id" in e ? e : S.createWorkflow(e), i = new g(s.id, t); Object.assign(i.globalContext, ((n = s.global) == null ? void 0 : n.context) || {}), r.breakpoints && r.breakpoints.forEach((o) => i.breakpoints.add(o)), this.executionStore.set(i.executionId, i); try { this.emitEvent("workflow.started", { context: i, workflow: s }); const o = this.buildDependencyGraph(s.steps); console.log("依赖图构建完成", { graph: o }); const u = await this.executeWorkflow(s, i, o); return console.log("工作流执行完成", { result: u }), i.status = "completed", i.endTime = Date.now(), this.emitEvent("workflow.completed", { context: i, workflow: s, result: u }), { executionId: i.executionId, status: i.status, result: u, context: i.serialize() }; } catch (o) { throw i.status = "failed", i.endTime = Date.now(), i.errors.push({ message: o instanceof Error ? o.message : String(o), stack: o instanceof Error ? o.stack : void 0, timestamp: Date.now() }), this.emitEvent("workflow.failed", { context: i, workflow: s, error: o }), console.error(`工作流 ${i.executionId} 执行失败:`, o), o; } } /** * 从断点继续执行 */ async resume(e) { const t = this.executionStore.get(e); if (!t) throw new Error(`Execution not found: ${e}`); if (t.status !== "paused") throw new Error(`Execution is not paused: ${e}`); return t.status = "running", t.isPaused = !1, this.emitEvent("workflow.resumed", { context: t }), { status: "resumed", executionId: e }; } /** * 暂停执行 */ async pause(e) { const t = this.executionStore.get(e); if (!t) throw new Error(`Execution not found: ${e}`); return t.status = "paused", t.isPaused = !0, this.emitEvent("workflow.paused", { context: t }), { status: "paused", executionId: e }; } /** * 取消执行 */ async cancel(e) { const t = this.executionStore.get(e); if (!t) throw new Error(`Execution not found: ${e}`); return t.status = "cancelled", this.emitEvent("workflow.cancelled", { context: t }), { status: "cancelled", executionId: e }; } /** * 获取执行状态 */ getExecutionStatus(e) { const t = this.executionStore.get(e); return t ? { executionId: t.executionId, status: t.status, startTime: t.startTime, endTime: t.endTime, currentStep: t.currentStep, completedSteps: Array.from(t.completedSteps), failedSteps: Array.from(t.failedSteps), errors: t.errors } : null; } /** * 构建依赖图 */ buildDependencyGraph(e) { const t = /* @__PURE__ */ new Map(); for (const r of e) t.set(r.id, { step: r, dependencies: r.dependsOn || [], dependents: [] }); for (const [r, s] of t.entries()) for (const i of s.dependencies) { const n = t.get(i); n && n.dependents.push(r); } return t; } /** * 执行工作流 */ async executeWorkflow(e, t, r) { const s = [], i = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), o = {}, u = Array.from(r.values()).filter((d) => d.dependencies.length === 0).map((d) => d.step); console.log("入口步骤", { entrySteps: u }); for (const d of u) s.push(d); for (; s.length > 0 || i.size > 0; ) { if (t.isPaused) { console.log("工作流暂停", { context: t }); break; } const d = s.filter((a) => !i.has(a.id) && (a.dependsOn || []).every((l) => n.has(l))); if (d.length === 0 && i.size === 0 && s.length === 0) { console.log("所有步骤执行完毕或没有可执行的步骤,退出循环"); break; } if (d.length === 0 && i.size > 0) { await new Promise((a) => setTimeout(a, 50)); continue; } d.length === 0 && s.length > 0 && i.size === 0 && console.warn("执行队列中没有就绪的步骤,但队列不为空且无正在执行的步骤。可能存在依赖问题。", { executionQueue: s.map((a) => a.id), executing: Array.from(i), completed: Array.from(n) }); const h = d.map(async (a) => { i.add(a.id); try { const l = await this.executeStep(a, t, e); o[a.id] = l, t.setStepResult(a.id, l), t.completedSteps.add(a.id), n.add(a.id); const f = Array.from(r.values()).filter((p) => p.dependencies.includes(a.id)).map((p) => p.step).filter((p) => !s.includes(p) && !i.has(p.id) && !n.has(p.id)); s.push(...f); } catch (l) { if (t.failedSteps.add(a.id), t.errors.push({ stepId: a.id, message: l instanceof Error ? l.message : String(l), stack: l instanceof Error ? l.stack : void 0, timestamp: Date.now() }), a.onError === "throw") throw l; if (a.onError === "continue") { console.warn(`步骤 ${a.id} 执行失败,但错误处理策略为 'continue'。错误:`, l instanceof Error ? l.message : String(l)), t.setStepResult(a.id, { error: l instanceof Error ? l.message : String(l), continued: !0 }), n.add(a.id); const f = Array.from(r.values()).filter((p) => p.dependencies.includes(a.id)).map((p) => p.step).filter((p) => !s.includes(p) && !i.has(p.id) && !n.has(p.id)); s.push(...f); } else if (a.onError === "retry") throw l; } finally { i.delete(a.id); } }); for (const a of d) { const l = s.findIndex((f) => f.id === a.id); l > -1 && s.splice(l, 1); } h.length > 0 && await Promise.race(h); } return o; } /** * 执行单个步骤 */ async executeStep(e, t, r) { var d, h, a, l; if (t.currentStep = e.id, this.emitEvent("step.started", { step: e, context: t }), e.condition && !C.evaluate(e.condition, t)) return t.skippedSteps.add(e.id), this.emitEvent("step.skipped", { step: e, context: t, reason: "condition" }), null; if (t.breakpoints.has(e.id)) return t.isPaused = !0, t.status = "paused", this.emitEvent("step.breakpoint", { step: e, context: t }), null; const s = m.mapInput(t.initialData, e.inputMapping || {}, t), i = e.input || ((d = this.handlerRegistry.getMetadata(e.handler)) == null ? void 0 : d.inputSchema); if (i) { const f = k.validate(s, i); if (!f.valid) { const p = `步骤 "${e.id}" 的输入数据验证失败: ${f.errors.join("; ")}`; throw this.emitEvent("step.validation_failed", { step: e, context: t, errors: f.errors, inputData: s }), new Error(p); } } const n = ((h = e.retry) == null ? void 0 : h.maxRetries) || 0, o = ((a = e.retry) == null ? void 0 : a.delay) || 1e3; let u = null; for (let f = 0; f <= n; f++) try { const p = e.timeout || ((l = r.global) == null ? void 0 : l.timeout) || this.config.defaultTimeout, w = new Promise((H, E) => { setTimeout(() => E(new Error(`Step timeout: ${e.id}`)), p); }), x = this.handlerRegistry.executeHandler(e.handler, s, t), b = await Promise.race([ x, w ]); return this.emitEvent("step.completed", { step: e, context: t, result: b }), b; } catch (p) { u = p, f < n && (this.emitEvent("step.retry", { step: e, context: t, error: p, attempt: f + 1, maxRetries: n }), await new Promise((w) => setTimeout(w, o))); } throw this.emitEvent("step.failed", { step: e, context: t, error: u }), u; } /** * 发送事件 */ emitEvent(e, t) { this.eventEmitter.emit(e, { detail: t }); } /** * 添加事件监听器 */ on(e, t) { this.eventEmitter.on(e, t); } /** * 移除事件监听器 */ off(e, t) { this.eventEmitter.off(e, t); } /** * 获取所有可用的处理器元数据 * @returns 所有注册的处理器元数据列表 */ getAvailableHandlers() { return this.handlerRegistry.getAllMetadata(); } /** * 获取特定处理器的元数据 * @param handlerName 处理器名称 * @returns 处理器元数据,如果不存在返回undefined */ getHandlerMetadata(e) { return this.handlerRegistry.getMetadata(e); } /** * 获取工作流步骤的详细信息(包括输入输出Schema) * @param workflowDefinition 工作流定义 * @returns 工作流步骤的详细信息 */ getWorkflowStepsInfo(e) { return e.steps.map((t) => { var s; const r = this.handlerRegistry.getMetadata(t.handler); return { id: t.id, name: t.name, type: t.type, handler: t.handler, inputSchema: t.input || (r == null ? void 0 : r.inputSchema) || { type: "object", properties: {} }, outputSchema: t.output || (r == null ? void 0 : r.outputSchema) || { type: "object", properties: {} }, description: (s = t.metadata) == null ? void 0 : s.description, handlerMetadata: r }; }); } } class L { constructor() { this.workflow = { id: v(), name: "", version: "1.0.0", description: "", global: { timeout: 3e4, retryPolicy: { maxRetries: 3, delay: 1e3 }, context: {}, variables: {} }, input: { type: "object", properties: {} }, output: { type: "object", properties: {} }, steps: [], dependencies: [], conditions: [], errorHandlers: [], metadata: {} }; } /** * 设置基本信息 */ setBasicInfo(e) { return this.workflow.name = e.name, e.description && (this.workflow.description = e.description), e.version && (this.workflow.version = e.version), e.id && (this.workflow.id = e.id), this; } /** * 设置全局配置 */ setGlobalConfig(e) { return this.workflow.global || (this.workflow.global = {}), e.timeout && (this.workflow.global.timeout = e.timeout), e.retryPolicy && (this.workflow.global.retryPolicy = e.retryPolicy), e.context && (this.workflow.global.context = { ...this.workflow.global.context, ...e.context }), e.variables && (this.workflow.global.variables = { ...this.workflow.global.variables, ...e.variables }), this; } /** * 添加步骤 */ addStep(e) { this.workflow.steps || (this.workflow.steps = []); const t = new j(e); return this.workflow.steps.push(t), this; } /** * 更新步骤 */ updateStep(e, t) { if (!this.workflow.steps) return this; const r = this.workflow.steps.findIndex((s) => s.id === e); return r !== -1 && (this.workflow.steps[r] = { ...this.workflow.steps[r], ...t }), this; } /** * 删除步骤 */ removeStep(e) { return this.workflow.steps ? (this.workflow.steps = this.workflow.steps.filter((t) => t.id !== e), this) : this; } /** * 添加依赖关系 */ addDependency(e, t, r) { if (!this.workflow.steps) throw new Error("工作流中没有任何步骤,无法添加依赖"); const s = this.workflow.steps.find((o) => o.id === e), i = this.workflow.steps.find((o) => o.id === t); if (!s) throw new Error(`依赖的源步骤不存在: ${e}`); if (!i) throw new Error(`依赖的目标步骤不存在: ${t}`); const n = this.workflow.steps.find((o) => o.id === t); return n && (n.dependsOn || (n.dependsOn = []), n.dependsOn.includes(e) || n.dependsOn.push(e)), this.workflow.dependencies || (this.workflow.dependencies = []), this.workflow.dependencies.push({ from: e, to: t, type: r }), this; } /** * 移除依赖关系 */ removeDependency(e, t) { if (this.workflow.steps) { const r = this.workflow.steps.find((s) => s.id === t); r && r.dependsOn && (r.dependsOn = r.dependsOn.filter((s) => s !== e)); } return this.workflow.dependencies && (this.workflow.dependencies = this.workflow.dependencies.filter((r) => !(r.from === e && r.to === t))), this; } /** * 设置输入Schema */ setInputSchema(e) { return this.workflow.input = e, this; } /** * 设置输出Schema */ setOutputSchema(e) { return this.workflow.output = e, this; } /** * 添加条件规则 */ addConditionRule(e) { return this.workflow.conditions || (this.workflow.conditions = []), this.workflow.conditions.push(e), this; } /** * 添加错误处理器 */ addErrorHandler(e) { return this.workflow.errorHandlers || (this.workflow.errorHandlers = []), this.workflow.errorHandlers.push(e), this; } /** * 验证工作流 */ validate() { const e = []; if (this.workflow.name || e.push("工作流名称是必需的"), !this.workflow.steps || this.workflow.steps.length === 0) e.push("至少需要一个步骤"); else { const t = this.workflow.steps.map((s) => s.id); if (new Set(t).size !== t.length) { const s = t.filter((i, n) => t.indexOf(i) !== n); e.push(`存在重复的步骤ID: ${s.join(", ")}`); } for (const s of this.workflow.steps) if (s.dependsOn) for (const i of s.dependsOn) t.includes(i) || e.push(`步骤 ${s.id} 依赖不存在的步骤: ${i}`); this.hasCyclicDependency() && e.push("检测到循环依赖"); } return { valid: e.length === 0, errors: e }; } /** * 检查循环依赖 */ hasCyclicDependency() { if (!this.workflow.steps) return !1; const e = /* @__PURE__ */ new Map(); for (const i of this.workflow.steps) e.set(i.id, i.dependsOn || []); const t = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), s = (i) => { if (r.has(i)) return !0; if (t.has(i)) return !1; t.add(i), r.add(i); const n = e.get(i) || []; for (const o of n) if (s(o)) return !0; return r.delete(i), !1; }; for (const i of e.keys()) if (s(i)) return !0; return !1; } /** * 构建工作流 */ build() { const e = this.validate(); if (!e.valid) throw new Error(`工作流验证失败: ${e.errors.join(", ")}`); return S.createWorkflow(this.workflow); } /** * 导出为JSON字符串 */ toJSON() { return JSON.stringify(this.workflow, null, 2); } /** * 从JSON导入 */ fromJSON(e) { let t; if (typeof e == "string") try { t = JSON.parse(e); } catch (r) { throw new Error(`无效的JSON字符串: ${r.message}`); } else t = e; return this.workflow = { ...this.workflow, ...t }, this; } } const B = { maxConcurrentExecutions: 10, defaultTimeout: 3e4, enableBreakpoints: !1, persistExecution: !1 }; export { y as BaseNode, C as ConditionEvaluator, B as DEFAULT_CONFIG, m as DataMapper, T as DelayNode, g as ExecutionContext, A as HttpNode, P as LogNode, D as NoopNode, k as SchemaValidator, j as StepDefinition, I as StepHandlerRegistry, O as TypeConvertNode, N as TypeConverter, L as WorkflowBuilder, S as WorkflowDSL, J as WorkflowEngine, R as getBuiltinNodes }; //# sourceMappingURL=flow-engine.es.js.map