jagreehal/effect-analyzer

GitHub: jagreehal/effect-analyzer

Effect-TS 程序的静态分析工具,通过解析源码生成结构可视化图表、复杂度指标和语义差异对比,帮助开发者理解和维护 Effect 代码。

Stars: 22 | Forks: 1

# effect-analyzer [Effect](https://effect.website/) 程序的静态分析工具。将服务依赖、错误通道、并发和控制流可视化为 Mermaid 图表——无需运行你的代码。 ## 为什么需要 Effect 程序功能强大,但其结构——服务依赖、错误拓扑、并发模式——在源代码中很难直接看出来。effect-analyzer 使用 [ts-morph](https://ts-morph.com/) 和 TypeScript 类型检查器解析你的代码,然后生成语义图表和结构化分析。无需运行时,无需埋点。 将其用于**代码审查**、**新手入门**、**架构文档**和 **CI**,以捕捉程序结构上的回归。 ## 安装 ``` npm install -D effect-analyzer ``` `effect` (>=3.0.0) 是必需的 peer dependency。`ts-morph` 会自动打包。 ## 快速开始 ``` # 为文件自动选择最佳图表 npx effect-analyze ./src/transfer.ts # Railway 图(线性 happy path 及 error 分支) npx effect-analyze ./src/transfer.ts --format mermaid-railway # 用纯英语解释程序的功能 npx effect-analyze ./src/transfer.ts --format explain # 比较两个版本 npx effect-analyze HEAD:src/transfer.ts src/transfer.ts --diff # 审查整个项目 npx effect-analyze ./src --coverage-audit ``` ## 你将获得什么 给定一个像这样的 Effect 程序: ``` export const transfer = Effect.gen(function* () { const repo = yield* AccountRepo const audit = yield* AuditLog const balance = yield* repo.getBalance("from-account") if (balance < 100) { yield* Effect.fail(new InsufficientFundsError(balance, 100)) } yield* repo.debit("from-account", 100) yield* repo.credit("to-account", 100) yield* audit.record("transfer-complete") }) ``` 分析器会生成一个轨道图,显示带有错误分支的正常路径: ``` flowchart LR A["repo <- AccountRepo"] -->|ok| B["audit <- AuditLog"] B -->|ok| C["balance <- repo.getBalance"] C -->|ok| D{"balance < 100"} D -->|ok| E["repo.debit"] E -->|ok| F["repo.credit"] F -->|ok| G["audit.record"] G -->|ok| Done((Success)) C -.->|err| Err1([AccountNotFound]) D -.->|err| Err2([InsufficientFunds]) ``` 或者生成一个显示所有控制流路径的流程图: ``` flowchart TB start((Start)) n2["repo <- AccountRepo"] n3["audit <- AuditLog"] n4["balance <- repo.getBalance"] decision{"balance < 100?"} n7["Effect.fail(InsufficientFunds)"] n8["repo.debit"] n9["repo.credit"] n10["audit.record"] end_node((Done)) start --> n2 --> n3 --> n4 --> decision decision -->|yes| n7 decision -->|no| n8 n7 -.-> end_node n8 --> n9 --> n10 --> end_node ``` ## 功能 ### 15+ 种图表类型 自动模式会为你的程序选择最相关的视图,你也可以显式选择: | 格式 | 显示内容 | |--------|-------| | `mermaid-railway` | 带有错误分支的线性正常路径 | | `mermaid` | 包含所有控制流的完整流程图 | | `mermaid-services` | 服务依赖图 | | `mermaid-errors` | 错误传播和处理 | | `mermaid-concurrency` | 并行和竞速模式 | | `mermaid-layers` | Layer 组合图 | | `mermaid-retry` | 重试和超时策略 | | `mermaid-timeline` | 随时间变化的步骤序列 | | `mermaid-statechart` | 作为 `stateDiagram-v2` 的状态机 | | `svg-statechart` | 独立的、XState 风格的 statechart SVG | | `statechart-html` | 带有 SVG、覆盖率和 XState 导出的本地可视化页面 | | `xstateconfig` | 用于 [Stately 可视化工具](https://stately.ai/viz)的 `createMachine()` 配置 | [查看所有格式 →](https://jagreehal.github.io/effect-analyzer/diagrams/all-formats/) ### 无需 XState 的状态机 用纯 Effect 编写确定性状态机——可以是声明式转换表、`Match.when` 转换函数,或嵌套的 `Match.tags` 状态/事件分发——并将它们渲染为 XState 风格的 statecharts。不需要 XState 依赖。请参阅 [`state-machine-conventions.md`](./state-machine-conventions.md) 中的完整约定指南。 ``` # 无 flags:默认视图会展示文件中的任何 state machine npx effect-analyze ./workflow.ts # 本地 visualizer 页面(diagram + coverage + 可粘贴的 config)。 # 若未指定 -o,它会在 input 旁边生成 workflow.statechart.html npx effect-analyze ./workflow.ts --format statechart-html # 适用于 markdown / GitHub 的 stateDiagram-v2 npx effect-analyze ./workflow.ts --format mermaid-statechart # XState createMachine() config — 粘贴到 stately.ai/viz 即可获得真实的 # interactive visualizer,直接由你的 Effect 代码生成 npx effect-analyze ./workflow.ts --format xstate-config ``` 可识别以下结构: ``` // A) declarative transition table const transitions = { Triage: { RefundRequested: { target: 'Refund', guard: 'canRefund' }, AnswerRequested: 'Answered', }, Refund: { Resolved: 'Answered' }, Answered: {}, } as const; // B) Match.when transition function const transition = (state: State, event: Event): State => Match.value([state._tag, event._tag] as const).pipe( Match.when(['Draft', 'Submit'], () => ({ _tag: 'Review' as const })), Match.orElse(() => state), ); // C) nested Match.tags with state tags outside and event tags inside const transitionWithTags = (state: State, event: Event): State => Match.value(state).pipe( Match.tags({ Draft: () => Match.value(event).pipe( Match.tags({ Submit: () => ({ _tag: 'Review' as const }), }), ), Review: () => state, }), ); ``` 初始状态从 `@initial ` 注解或 `initial`/`initialState` 声明中读取。表叶子节点可以是字符串、 `{ target, guard }`、`{ to }`,或者是受保护目标的数组。如果处理程序可以返回多个状态,则会变成受保护的(多目标)转换。 #### 完整性检查(感知 Schema) 当 State/Event 类型是可辨识联合或 `Schema` 派生类型时,分析器会读取**已声明的字母表**并根据它检查状态机——将 statechart 从一张图纸变成经过验证的机器: ``` npx effect-analyze ./workflow.ts --format statechart-coverage ``` ``` # State machine coverage 1 machine, 2 warnings. ## checkoutTransition(alphabet: schema) Coverage: 33% (2/6 reachable state×event pairs handled) - ⚠ Unhandled events: `Cancel` # declared, but no state handles it - ⚠ Unreachable states: `Cancelled` # declared, but nothing transitions to it ``` 它会报告**未处理的事件**、**无法到达的状态**以及**未声明的符号**(偏离了类型的转换)。该命令**在任何发现警告时都会以非零状态退出**,因此它可以作为 CI 门禁使用。 `mermaid-statechart` 和 `svg-statechart` 输出会使用相同的发现进行标注(高亮显示孤立状态,指出未处理的事件)。 在整个目录上运行它以获取摘要表、设置覆盖率下限,或为仪表板输出 JSON: ``` npx effect-analyze ./src --format statechart-coverage # all machines, summary table npx effect-analyze ./src --format statechart-coverage --min-coverage 60 # fail under 60% npx effect-analyze ./src --format statechart-coverage --coverage-json # { machines, summary } ``` 受保护的(条件)转换会连同其条件一起被捕获,并显示在每个渲染器上(图表中为 `Event [guard]`,XState 配置中为 `{ target, guard }`)。State/Event 字母表可以是可辨识联合、`Schema` 派生类型、`Schema.TaggedClass`/`Schema.TaggedRequest` 联合,或者是普通的字符串字面量联合(`'a' | 'b'`)。 除非存在嵌套的状态/事件结构,否则普通的单层 `Match.tags` 分发会被特意忽略,因为普通的变体处理不具备 statechart 所需的源状态维度。 ### 复杂度指标 为每个程序计算六项指标:圈复杂度、认知复杂度、路径数、嵌套深度、并行广度和决策点。 ``` npx effect-analyze ./src/transfer.ts --format stats ``` [了解更多 →](https://jagreehal.github.io/effect-analyzer/analysis/complexity/) ### 语义差异对比 在结构层面比较程序的两个版本——不是文本差异,而是步骤、服务和控制流的变化: ``` npx effect-analyze HEAD:src/transfer.ts src/transfer.ts --diff ``` [了解更多 →](https://jagreehal.github.io/effect-analyzer/project/diff/) ### 覆盖率审计 扫描整个项目以了解 Effect 的使用情况,识别复杂的程序,并跟踪分析质量: ``` npx effect-analyze ./src --coverage-audit ``` [了解更多 →](https://jagreehal.github.io/effect-analyzer/project/coverage-audit/) ### 交互式 HTML 查看器 生成一个独立的 HTML 页面,包含搜索、过滤、路径浏览器、复杂度热力图和 6 种颜色主题: ``` import { renderInteractiveHTML } from "effect-analyzer" const html = renderInteractiveHTML(ir, { theme: "midnight" }) ``` [了解更多 →](https://jagreehal.github.io/effect-analyzer/reference/html-viewer/) ### 库 API 使用编程 API 将分析集成到你自己的工具中: ``` import { analyze } from "effect-analyzer" import { Effect } from "effect" const ir = await Effect.runPromise(analyze("./src/transfer.ts").single()) console.log(ir.root.programName) // "transfer" console.log(ir.root.dependencies) // [{ name: "AccountRepo", ... }, ...] console.log(ir.root.errorTypes) // ["InsufficientFundsError", "AccountNotFoundError"] ``` [完整 API 参考 →](https://jagreehal.github.io/effect-analyzer/reference/api/) ## 可检测内容 | 领域 | 模式 | |------|----------| | **程序** | `Effect.gen`、管道链、`Effect.sync`、`Effect.async`、`Effect.promise` | | **服务** | 通过 `yield*` 调用的 `Context.Tag`、服务方法调用 | | **Layer** | `Layer.mergeAll`、`Layer.effect`、`Layer.provide`、`Layer.succeed` | | **错误** | `catchTag`、`catchAll`、`tapError`、`retry`、`timeout` | | **并发** | `Effect.all`、`Effect.race`、`Effect.fork`、`Fiber.join` | | **资源** | `acquireRelease`、`ensuring`、`Effect.scoped` | | **流** | `Stream.fromIterable`、`Stream.mapEffect`、`Stream.runCollect` | | **控制流** | 位于 generator 内部的 `if/else`、`for..of`、`while`、`try/catch`、`switch` | | **调度** | `Schedule.recurs`、`Schedule.exponential` | | **别名** | `const E = Effect`、解构导入、重命名导入 | ## 环境要求 - Node.js 22+ - 带有 `effect` (>=3.0.0) 的 TypeScript 项目 ## 文档 完整文档可在 **[jagreehal.github.io/effect-analyzer](https://jagreehal.github.io/effect-analyzer/)** 获取。 ## 许可证 MIT
标签:Mermaid, MITM代理, TypeScript, 云安全监控, 代码可视化, 安全专业人员, 安全插件, 架构分析, 自动化攻击, 静态分析