{"_id":"72flow-nodejs","_rev":"3-ea37059b0a759d23bc9c88a49d25a5a3","name":"72flow-nodejs","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"72flow-nodejs","version":"1.0.0","keywords":["workflow","orchestration","flow-engine","72flow","bpmn"],"author":{"name":"baipeng"},"license":"ISC","_id":"72flow-nodejs@1.0.0","maintainers":[{"name":"baipeng139","email":"baipeng139@gmail.com"}],"homepage":"https://github.com/baipeng1009472720/72flow-nodejs#readme","bugs":{"url":"https://github.com/baipeng1009472720/72flow-nodejs/issues"},"dist":{"shasum":"b73241d8143b119d4247a3136752db15f64ee4dd","tarball":"https://registry.npmjs.org/72flow-nodejs/-/72flow-nodejs-1.0.0.tgz","fileCount":7,"integrity":"sha512-bF5953m4jVz2BQzCV0eVbhjRlnRNVsJXfpJ97bJE6ZDYYevmEa4XCRhENXXgVFnAT44vfKdSh4Rj0SgeUuDgkA==","signatures":[{"sig":"MEQCIB+BCCnPOxhbsO1anh9yYit2U9YcasdpiNA9RcZhx4rXAiAQF7qTyso3WRlMXScKlea33f9qMpmI4TkM6hXk3nw0jQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109122},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"1205043856bc2f08e683d645138c84d94a145342","scripts":{"dev":"vitest","test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"baipeng139","email":"baipeng139@gmail.com"},"repository":{"url":"git+https://github.com/baipeng1009472720/72flow-nodejs.git","type":"git"},"_npmVersion":"10.8.3","description":"Node.js / browser implementation of the 72flow orchestration engine","directories":{},"_nodeVersion":"20.10.0","dependencies":{"lodash-es":"^4.18.1","@types/lodash-es":"^4.17.12"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.4","typescript":"^6.0.2","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/72flow-nodejs_1.0.0_1775996830797_0.007709239920898003","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"72flow-nodejs","version":"1.0.2","keywords":["workflow","orchestration","flow-engine","72flow","bpmn"],"author":{"name":"baipeng"},"license":"ISC","_id":"72flow-nodejs@1.0.2","maintainers":[{"name":"baipeng139","email":"baipeng139@gmail.com"}],"homepage":"https://github.com/baipeng1009472720/72flow-nodejs#readme","bugs":{"url":"https://github.com/baipeng1009472720/72flow-nodejs/issues"},"dist":{"shasum":"0130aceb3cbcd7538cfc9b64ce5c05d535f3954c","tarball":"https://registry.npmjs.org/72flow-nodejs/-/72flow-nodejs-1.0.2.tgz","fileCount":7,"integrity":"sha512-6d55K1i3PF4+D+tYsfCZz6U1ynyhpdmQGtZBXRMXJjnT7nQoajD0NZRxgtFdAeBuCClLAduWIUsZ8f8PoE5Elw==","signatures":[{"sig":"MEUCIAmo9Jt3f0ZBWfASi7NIQmMF9zoK+up8gDVvyk6MAczLAiEA51hhHbKX8xvQezx1fD7R7OUCiHVrr2MxbwCr2Gi9dE8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111511},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"cf0ccd3715dc0fc247760de617e0d4204fe61520","scripts":{"dev":"vitest","test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"baipeng139","email":"baipeng139@gmail.com"},"repository":{"url":"git+https://github.com/baipeng1009472720/72flow-nodejs.git","type":"git"},"_npmVersion":"10.8.3","description":"Node.js / browser implementation of the 72flow orchestration engine","directories":{},"_nodeVersion":"20.10.0","dependencies":{"lodash-es":"^4.18.1","@types/lodash-es":"^4.17.12"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","vitest":"^4.1.4","typescript":"^6.0.2","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/72flow-nodejs_1.0.2_1776000015286_0.3346088798501341","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"72flow-nodejs","version":"1.0.3","description":"Node.js / browser implementation of the 72flow orchestration engine","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"dev":"vitest","test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --clean","prepublishOnly":"npm run build"},"keywords":["workflow","orchestration","flow-engine","72flow","bpmn"],"author":{"name":"baipeng"},"license":"ISC","repository":{"type":"git","url":"git+https://github.com/baipeng1009472720/72flow-nodejs.git"},"bugs":{"url":"https://github.com/baipeng1009472720/72flow-nodejs/issues"},"homepage":"https://github.com/baipeng1009472720/72flow-nodejs#readme","devDependencies":{"@types/node":"^25.6.0","tsup":"^8.5.1","typescript":"^6.0.2","vitest":"^4.1.4"},"dependencies":{"@types/lodash-es":"^4.17.12","lodash-es":"^4.18.1"},"_id":"72flow-nodejs@1.0.3","gitHead":"4544c7b3fae2dc243971a3a45efd88b427c9ffef","_nodeVersion":"20.10.0","_npmVersion":"10.8.3","dist":{"integrity":"sha512-ZZV+momGUoq7rCyraEAvmQVKeqVDpuSbZHxSkPtnk+e0aWziqXQvpVNLZwQWloH8+gRqvizXn0788hZUxtoRxg==","shasum":"139b230902692a95da095ec778d197f6f91431a5","tarball":"https://registry.npmjs.org/72flow-nodejs/-/72flow-nodejs-1.0.3.tgz","fileCount":7,"unpackedSize":117240,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCID4xqFwrm3DgCAJwvtpPoGNaUJshZA63V0P//YQwdBHyAiEAoInf15loa3hy/TLKe6fxjDWs4Oc3HxP9BBHKngLfXLU="}]},"_npmUser":{"name":"baipeng139","email":"baipeng139@gmail.com"},"directories":{},"maintainers":[{"name":"baipeng139","email":"baipeng139@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/72flow-nodejs_1.0.3_1776005192602_0.18532450566554726"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-12T12:27:10.797Z","modified":"2026-04-12T14:46:32.860Z","1.0.0":"2026-04-12T12:27:10.924Z","1.0.2":"2026-04-12T13:20:15.437Z","1.0.3":"2026-04-12T14:46:32.746Z"},"bugs":{"url":"https://github.com/baipeng1009472720/72flow-nodejs/issues"},"author":{"name":"baipeng"},"license":"ISC","homepage":"https://github.com/baipeng1009472720/72flow-nodejs#readme","keywords":["workflow","orchestration","flow-engine","72flow","bpmn"],"repository":{"type":"git","url":"git+https://github.com/baipeng1009472720/72flow-nodejs.git"},"description":"Node.js / browser implementation of the 72flow orchestration engine","maintainers":[{"name":"baipeng139","email":"baipeng139@gmail.com"}],"readme":"# 72flow-nodejs\n\n[![NPM Version](https://img.shields.io/npm/v/72flow-nodejs.svg)](https://www.npmjs.com/package/72flow-nodejs)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![TypeScript](https://img.shields.io/badge/TypeScript-6.x-blue)](https://www.typescriptlang.org/)\n[![Node.js](https://img.shields.io/badge/Node.js-18%2B-green)](https://nodejs.org/)\n\n**72flow-nodejs** 是 72flow 工作流编排引擎的轻量级 JavaScript 实现。它旨在提供一个与 Java 后端行为完全一致的、可在浏览器和 Node.js 环境中无缝运行的流程执行核心。\n\n---\n\n## 核心特性\n\n- 🚀 **极轻量**：无重度依赖，压缩后产物极小。\n- ✅ **全能力节点**：支持 START、END、SCRIPT、DECISION、CONDITION、PARALLEL、LOOP、API、LLM 等 9 种核心节点。\n- ✅ **双运行时**：天然支持现代浏览器与 Node.js 18+ 环境。\n- ✅ **精准输出**：END 节点支持根据 `sourceCode` 路由特定节点的产物作为流程结果。\n- ✅ **脚本捕获**：SCRIPT 节点支持捕获显式 `return` 的值。\n- ✅ **X6 友好**：内置对 `@antv/x6` 导出的图形 JSON 的原生解析支持。\n- ✅ **事件驱动**：完整的生命周期钩子（starting, completed, failed）。\n- ✅ **零配置 LLM**：内置对 OpenAI 协议大模型的支持。\n\n---\n\n## 安装\n\n```bash\nnpm install 72flow-nodejs\n```\n\n> 需要 Node.js **18+**（使用原生 `fetch` 和 `EventTarget`）\n\n---\n\n## 快速开始\n\n### 基础线性流程\n\n```typescript\nimport { FlowEngine, FlowDefinition, NodeType } from '72flow-nodejs';\n\nconst definition: FlowDefinition = {\n  id: 'hello-world',\n  name: 'Hello World',\n  version: '1.0',\n  nodes: [\n    { id: 'start',  type: NodeType.START },\n    { id: 'script', type: NodeType.SCRIPT, config: { script: 'greeting = \"Hello, \" + name' } },\n    { id: 'end',    type: NodeType.END },\n  ],\n  edges: [\n    { id: 'e1', from: 'start',  to: 'script' },\n    { id: 'e2', from: 'script', to: 'end' },\n  ],\n};\n\nconst engine = new FlowEngine();\nconst result = await engine.execute(definition, { name: 'World' });\n\nconsole.log(result.status);           // 'COMPLETED'\nconsole.log(result.variables.greeting); // 'Hello, World'\n```\n\n### 条件分支（DECISION）\n\n```typescript\nconst definition: FlowDefinition = {\n  id: 'branch-demo',\n  name: '条件分支示例',\n  version: '1.0',\n  nodes: [\n    { id: 'start',    type: NodeType.START },\n    { id: 'decision', type: NodeType.DECISION, config: { decision: { scriptCode: 'score >= 60 ? \"pass\" : \"fail\"' } } },\n    { id: 'pass',     type: NodeType.SCRIPT, config: { script: 'result = \"通过\"' } },\n    { id: 'fail',     type: NodeType.SCRIPT, config: { script: 'result = \"未通过\"' } },\n    { id: 'end',      type: NodeType.END },\n  ],\n  edges: [\n    { id: 'e1', from: 'start',    to: 'decision' },\n    { id: 'e2', from: 'decision', to: 'pass', condition: 'pass' },\n    { id: 'e3', from: 'decision', to: 'fail', condition: 'fail' },\n    { id: 'e4', from: 'pass',     to: 'end' },\n    { id: 'e5', from: 'fail',     to: 'end' },\n  ],\n};\n\nconst result = await new FlowEngine().execute(definition, { score: 80 });\nconsole.log(result.variables.result); // '通过'\n```\n\n### 并行分支（PARALLEL）\n\n```typescript\nconst definition: FlowDefinition = {\n  id: 'parallel-demo',\n  name: '并行流程示例',\n  version: '1.0',\n  nodes: [\n    { id: 'start',   type: NodeType.START },\n    { id: 'par',     type: NodeType.PARALLEL },\n    { id: 'taskA',   type: NodeType.SCRIPT, config: { script: 'a = 1' } },\n    { id: 'taskB',   type: NodeType.SCRIPT, config: { script: 'b = 2' } },\n    { id: 'join',    type: NodeType.SCRIPT, config: { script: 'sum = a + b' } },\n    { id: 'end',     type: NodeType.END },\n  ],\n  edges: [\n    { id: 'e1', from: 'start',  to: 'par' },\n    { id: 'e2', from: 'par',    to: 'taskA' },\n    { id: 'e3', from: 'par',    to: 'taskB' },\n    { id: 'e4', from: 'taskA',  to: 'join' },\n    { id: 'e5', from: 'taskB',  to: 'join' },\n    { id: 'e6', from: 'join',   to: 'end' },\n  ],\n  convergeMap: { par: 'join' }, // 声明汇聚关系\n};\n\nconst result = await new FlowEngine().execute(definition, {});\nconsole.log(result.variables.sum); // 3\n```\n\n### 监听引擎事件\n\n```typescript\nconst engine = new FlowEngine();\n\nengine.on('node.starting',   ({ nodeId }) => console.log(`▶ 开始: ${nodeId}`));\nengine.on('node.completed',  ({ nodeId, output }) => console.log(`✓ 完成: ${nodeId}`, output));\nengine.on('node.failed',     ({ nodeId, error }) => console.error(`✗ 失败: ${nodeId}`, error));\n\nawait engine.execute(definition, variables);\n```\n\n### 解析 X6 画布 JSON\n\n```typescript\nimport { parseX6 } from '72flow-nodejs';\n\n// x6Json 是 @antv/x6 画布导出的 JSON 对象\nconst flowDefinition = parseX6(x6Json);\nconst result = await new FlowEngine().execute(flowDefinition, {});\n```\n\n---\n\n## 节点类型说明\n\n| 节点类型    | 说明                                             | 关键配置字段                                     |\n|-------------|--------------------------------------------------|-------------------------------------------------|\n| `START`     | 流程起始节点                                     | —                                               |\n| `END`       | 流程结束周期。支持精准提取指定节点产物            | `config.outputResult.sourceCode`                |\n| `SCRIPT`    | 执行 JavaScript 脚本。支持 `scriptResult` 返回值   | `config.script.scriptCode`                      |\n| `DECISION`  | 运行脚本计算返回值，与出边 `condition` 字段匹配   | `config.decision.scriptCode`                    |\n| `CONDITION` | 对每条出边独立求值布尔表达式                       | `config.condition.scriptCode`                   |\n| `PARALLEL`  | 并发触发所有出边分支，需配合 `convergeMap` 使用   | `convergeMap` (流程定义级)                       |\n| `LOOP`      | 数组/次数迭代，内联执行循环体                     | `config.loop.loopType` / `itemsExpr` / `itemVar`|\n| `API`       | 调用 HTTP 接口，结果写入 `apiResponse` 变量       | `config.api.url` / `method` / `headers` / `body`|\n| `LLM`       | 调用 OpenAI 兼容大语言模型接口                    | `config.llm.provider` / `modelName` / `userPrompt` |\n\n---\n\n## 流程变量\n\n- 引擎所有节点**共享同一个变量空间**（`FlowContext.variables`）\n- `SCRIPT` 节点通过 `with(vars)` 语法直接读写变量，**新增的变量也会生效**\n- `API` 节点完成后，响应体自动写入 `variables.apiResponse`\n- `LLM` 节点完成后，模型回复写入 `variables.llmResponse`\n- `LOOP` 节点每轮迭代将当前元素写入 `item`（可自定义 `itemVar`），索引写入 `index`（可自定义 `indexVar`）\n\n---\n\n## 错误处理\n\n节点可在 `config.error.mode` 中指定错误处理策略：\n\n| 值              | 行为                                |\n|----------------|-------------------------------------|\n| `\"throw\"`      | 抛出异常，终止流程（默认）            |\n| `\"fail\"`       | 标记流程失败，终止流程               |\n| `\"<nodeId>\"`   | 跳转到指定节点 ID 继续执行（兜底逻辑）|\n\n---\n\n## API 参考\n\n### `FlowEngine`\n\n```typescript\nclass FlowEngine {\n  // 执行流程定义，返回执行结果\n  execute(definition: FlowDefinition, variables?: Record<string, any>): Promise<FlowResult>;\n\n  // 事件监听（继承自 SimpleEmitter）\n  on(event: string, handler: Function): this;\n  once(event: string, handler: Function): this;\n  off(event: string, handler: Function): this;\n}\n```\n\n### `FlowResult`\n\n```typescript\ninterface FlowResult {\n  executionId: string;            // 本次执行唯一 ID\n  status: NodeStatus;             // COMPLETED | FAILED | CANCELLED\n  output?: any;                   // END 节点的输出\n  error?: string;                 // 错误信息（失败时）\n  duration: number;               // 执行耗时（ms）\n  startTime: number;              // 开始时间戳（ms）\n  endTime?: number;               // 结束时间戳（ms）\n  variables: Record<string, any>; // 最终变量快照\n  traces: TraceRecord[];          // 各节点执行轨迹\n}\n```\n\n### `parseX6(x6Json)`\n\n将 `@antv/x6` 导出的画布 JSON 转为 `FlowDefinition`，自动规范化节点类型、loop 配置字段等。\n\n---\n\n## 开发\n\n```bash\n# 安装依赖\nnpm install\n\n# 运行测试（watch 模式）\nnpm run dev\n\n# 单次运行所有测试\nnpm test\n\n# 构建 ESM + CJS 产物\nnpm run build\n```\n\n### 项目结构\n\n```\nsrc/\n├── index.ts              # 公开导出入口\n├── types/\n│   └── models.ts         # 核心类型定义（FlowDefinition、NodeDef、FlowResult 等）\n├── core/\n│   ├── flow-engine.ts    # 流程引擎调度核心\n│   ├── flow-context.ts   # 执行上下文（变量、状态、轨迹）\n│   └── flow-engine.test.ts # 集成测试\n├── executors/\n│   └── factory.ts        # 各类型节点执行器（Start/End/Script/Decision/Parallel/Loop/API/LLM）\n├── parser/\n│   └── x6-parser.ts      # X6 画布 JSON 解析器\n└── support/\n    └── logger.ts         # 轻量日志工具\n```\n\n---\n\n## 与 Java 引擎的差异\n\n| 能力              | Node.js 引擎  | Java 引擎      |\n|-------------------|--------------|----------------|\n| SCRIPT 语言        | **JavaScript only** | JavaScript + Groovy |\n| API 跨域（浏览器）  | 需 Vite `/api-proxy` 代理 | 无限制 |\n| 运行环境           | Node.js 18+ / 现代浏览器 | JVM 11+ |\n\n> **注意**：在浏览器中调用 `API` 节点时，需确保 Vite dev server 已配置 `/api-proxy` 代理路由，以规避 CORS 限制。\n\n---\n\n## License\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}