@integr8-media/flow-checker

中文文档
0.2.2发布于 2026/11/01MITTypeScriptESM + CJS构建来源已验证

映射一个Next.js应用路由器项目:页面、组件、请求、类型和流,根据实时流量进行验证,并导出为文档。

中文使用文档
文档目录19 节
  1. 它是做什么的
  2. 要求
  3. 15.3之前的Next.js
  4. 命令
  5. 指示板
  6. 反应查询
  7. 中间件
  8. tRPC
  9. 邮差集合
  10. GraphQL
  11. 服务器发送的事件
  12. 尚
  13. 详细设置
  14. 服务器钩子首先进入 register()
  15. 配置
  16. 敏感数据
  17. 文件
  18. 限制
  19. 许可证

flow-checker

映射一个Next.js 应用路由器 项目(它的页面,组件,请求,类型和用户流),当你使用应用程序时,根据实际流量检查地图,并将其导出为文档。

npm install -D @integr8-media/flow-checker
npx flow-checker init     # adds two capture hooks and a config file
npx flow-checker          # scans, opens the dashboard and starts your app with capture on

然后像往常一样使用你的应用。应用程序发送的每个请求都显示在仪表板上,并链接到发送请求的代码行。

它是做什么的

  • 扫描代码。 路由(组,动态,捕获,并行和拦截段,next-intl) [locale]),具有服务器/客户端边界的组件树,以及每个请求: fetch、axios、您自己的包装器客户端(以及您列出的任何HTTP库或API客户端包) apiClients), React Query, SWR, tRPC (v10和v11: hooks, vanilla客户端和v11) queryOptions()GraphQL(阿波罗客户端3和4,urql和Relay:按名称操作,从代码根,Relay编译器或模式键入),服务器发送的事件(new EventSource() 和流 fetch,每个监听的事件及其数据类型),WebSockets (new WebSocket() 和套接字。服务器操作(Server Actions)和路由处理程序(包括到后端的第二跳)。它还可以找到页面之间的导航(Link, router.push, redirect),并推断用户流,例如 登录→验证OTP→仪表盘. 中间件(middleware.ts,或者 proxy.ts 在Next.js上16)也被读取:它的路由 config.matcher 它的选择,它的重定向(以及每个重定向的条件),它的重写(用于告诉哪个页面响应了URL)以及它发送的请求。请求主体、响应和道具的类型由TypeScript编译器完全解析。
  • 捕捉真实流量 在浏览器和服务器上进行测试时,使用密码、令牌和验证头 在任何东西被保存之前被蒙面.
  • 验证映射。 每个捕获都与发送它的请求站点相匹配,从而标记该站点 ✓ verified. 将捕获的数据与声明的类型(缺失字段、额外字段、错误类型、意外)进行比较 null),当你走的时候,流是确定的。
  • 根据Postman集合检查代码 (可选):集合没有的请求,端点没有调用,以及保存示例中的类型。
  • 跟上你的编辑。 文件被监视并逐渐重新扫描。捕获后代码发生变化的请求将被标记 ↻ needs re-check.
  • 出口文档: Markdown(带有Mermaid路线图和序列图)和仪表板的静态只读副本,您可以在任何地方托管。

要求

支持
Next.js13.4及以后的版本,仅支持应用路由器 pages/ 未扫描目录)
node . js22.12或更高版本(22.18+)加载 flow-checker.config.ts)
操作系统Windows, macOS, Linux
软件包管理器Npm, pnpm, yarn, bun(从lockfile中检测)

15.3之前的Next.js

js 15.3添加了 instrumentation-client 加载浏览器钩子的文件。在13.4-15.2中,用 withFlowChecker() 所以相同的钩子文件工作(在13.4-14)。X也打开 experimental.instrumentationHook 对于服务器钩子):

// next.config.mjs
import { withFlowChecker } from '@integr8-media/flow-checker/next'

export default withFlowChecker({
  // your config
})
// next.config.js (CommonJS)
const { withFlowChecker } = require('@integr8-media/flow-checker/next')

module.exports = withFlowChecker({})

除非应用程序是由flow-checker启动的,否则它不会改变任何东西,并且在15.3及以后的版本中返回未修改的配置。在这些版本中,浏览器捕获需要webpack: run next dev 没有 --turbo. flow-checker init 和 flow-checker doctor 当你需要的时候告诉你。

命令

flow-checker            # same as `dev`
flow-checker dev        # scan + watch + dashboard + start your app with capture on
flow-checker scan       # scan only, write .flow-checker/model.json
flow-checker init       # add the capture hooks, a config file and .gitignore entries
flow-checker export     # Markdown docs and/or a static HTML site
flow-checker doctor     # check Node, Next.js, hooks, tsconfig, ports and .gitignore
flow-checker postman import   # read a Postman collection to check the code against
选项命令意义
--root <dir>所有项目根目录(默认:当前目录)
--app-dir <dir>所有应用路由器目录(默认: src/app 或者 app)
--config <file>Dev,扫描,导出,医生配置文件(默认: flow-checker.config.* 在根)
--port <n>dev,医生仪表板端口(默认为4400)
--app-port <n>dev,医生你的应用运行端口(默认为3000)
--dev-command <cmd>dev启动应用程序的命令(默认:the dev 脚本,或 next dev)
--no-appdev不要启动应用程序,用环境自己启动它 dev 打印。
--no-opendev不要打开浏览器
--no-watchdev当文件更改时,不要重新扫描
-y, --yes初始化无需询问就应用更改
--tree, --types, --requests, --flows扫描还要打印路由/组件树、解析类型、请求站点或流
--md <dir>, --html <dir>出口将Markdown文档/静态站点写入此文件夹。Neither: both,放到配置的文件夹中。
--raw出口将捕获保持为已保存状态,而不必再次编辑它们
--force出口写入包含其他文件的文件夹
--collection <src>邮差进口v2.1 JSON文件,v3 YAML文件夹或云集合id(默认: postman.collection)
--environment <src>邮差进口环境文件或云id {{variables}}
--api-key-env <name>邮差进口带有Postman API密钥的Env变量,用于云id(默认) POSTMAN_API_KEY)
--verbose所有还要打印解析后的配置、扫描运行的位置和其他详细信息
-q, --quiet所有没有进度输出:只有结果、警告和错误

每个命令在stderr上显示其进度。在终端中,活跃线显示了一个旋转器、一个用于整个命令的条、当前步骤及其时间,并且每个完成的步骤都会留下一个 ✓ 与它的发现相符:

✓ Loaded: 1,806 files (3.8 s)
✓ Routes: 401 pages, 200 route handlers (0.2 s)
⠸ [█████████░░░░░░░░░░░]  47%  Walking components… route 300/601  1.3 s

在CI中,当输出是管道的时候,或者使用 NO_COLOR / TERM=dumb,只有 ✓ 行作为纯文本打印。

指示板

flow-checker dev 服务于端口4400上的仪表板。相同的屏幕位于静态HTML导出中,只读。

  • 概述: 计算页面、路由处理程序、组件、请求、类型和流,每个都有指向其列表的链接,以及要检查的内容(未解析的url、未知的触发器、类型不匹配……),每个请求一个注释。
  • 地图: 路线图(图表或树)。一个页面显示了它的组件树,它在加载和事件时发送的请求(除了它的布局在每个页面上发送的请求),它通向哪里,以及它开始的流。
  • 组件: 每个组件,可按名称或文件搜索,按类型(服务器/客户端/共享)过滤,按它所拥有的(发送请求,要检查的东西,不在任何页面上)排序,并按名称,请求或页面排序。
  • 请求: 每个请求站点,可通过URL、组件或文件进行搜索,根据发送时间(加载、事件、服务器端、未知触发器)、状态(已验证、不匹配、需要重新检查、尚未捕获)、传输和标志进行筛选。从多个地方发送的相同请求是一行。请求在其自己的页面上打开,其中包含其主体和响应类型、服务器跳点、查询缓存链接、捕获和来自组件的调用路径。
  • 流, 类型, 生活 (在它们到达时捕获它们,并进行匹配和类型检查)和 出口.

过滤器和搜索保留在URL中,因此过滤后的列表可以被添加书签或共享。随着应用增长的列表(缓存调用命中的查询,路由处理程序的调用者…)显示5个条目,然后“+N个”。

反应查询

useQuery, useInfiniteQuery悬疑的钩子, useQueries / useSuspenseQueries (每个条目一个请求), useMutation, usePrefetchQuery 和 queryClient.fetchQuery / prefetchQuery / ensureQueryData (及其无限形式)是请求站点,在v4和v5中。每个查询的键被读入段(['todos', 'detail', :id]),也通过重点工厂, queryOptions() 以及返回选项的函数。

invalidateQueries, refetchQueries, resetQueries, removeQueries 和 setQueryData 链接到他们的关键命中的查询(通过前缀或 exact)以及回调调用它们的突变,因此流显示了突变刷新的查询。一个服务器端 prefetchQuery 交给… HydrationBoundary (v4: Hydrate)链接到它所填充的客户端查询。在测试时,查询或突变发送的每个请求都携带其键,并且捕获与它匹配。

中间件

middleware.ts (和 proxy.ts 在Next.js中16)为其读取 config.matcher:每个页面显示中间件是否在其上运行。 NextResponse.redirect() 变成了路线图上的一条边缘,周围的环境(if !token), NextResponse.rewrite() 和next-intl的默认语言环境用于告诉哪个页面回答了捕获的URL,并且中间件发送的请求得到一个 middleware 触发器。在Node.js (proxy.ts)这些请求像服务器的其他部分一样被捕获;在边缘运行时,尽最大努力(参见 限制)。

tRPC

过程调用是v10和v11中的请求站点: createTRPCReact 钩子(trpc.todo.byId.useQuery())、普通客户端(client.todo.add.mutate()), utils 电话和v11 useTRPC() 与 queryOptions() / mutationOptions(). 路由器是从路由处理程序中读取的 fetchRequestHandler() (或客户的 AppRouter 类型),因此每个调用都获得其过程的输入类型(从 .input())和不带注释的输出类型。在您进行测试时,一个批处理请求被拆分为每个过程的一个捕获,每个捕获都自己进行匹配和类型检查。

邮差集合

将流检查器指向一个Postman集合(配置 postman,或者 flow-checker postman import --collection <src>),并且每次扫描都要进行检查:

  • 代码中的每个请求都通过方法和URL ({{baseUrl}}/users/:id 适合 `${API}/users/${id}`). 该集合没有的请求被标记 未收;收集请求没有调用被列为 未使用的端点.
  • 保存的响应示例为代码为none(标记为“from Postman example”)的请求提供一个类型,然后根据它检查捕获。当代码声明类型时,将根据示例(合同不匹配)。
  • 扫描无法解析的URL将从其函数名和方法指向的集合请求中填充,只要其中一个正好合适。

postman import 打印摘要和调查结果列表;仪表板概述和Markdown导出(postman.md)也给他们看看。

GraphQL

Apollo Client(3和4)、urql和Relay调用是请求站点,每个操作调用一个。每个操作都指向相同的URL,因此捕获通过操作名称或持久化查询id进行匹配。批处理请求被拆分为每个操作的一个捕获,并进行类型检查比较 variables 和 data.

类型首先来自调用时的类型参数、代码根的类型化文档或Relay编译器。没有这些,设置 graphql.schema (或者让流检查器查找 schema.graphql / Relay或codegen配置中的模式),或者 graphql.introspection 要询问正在运行的端点(参见 配置). 仪表板概述列出了每个操作及其类型和调用者,以及读取它们的组件的片段。

服务器发送的事件

new EventSource(url) 和一个 fetch 作为事件流读取(Accept: text/event-stream,或者对一个路由处理程序的任何取回 text/event-stream)是请求站点。扫描列出了每个人收听的事件(onmessage, addEventListener('tick', ...)),其数据读取类型为(JSON.parse(e.data) as Tick, const t: Tick = JSON.parse(e.data), MessageEvent<Tick>),并读取路由处理程序写入的事件(event: tick / data: ${JSON.stringify(tick)},也通过一个帮手喜欢 send('tick', tick)). 事件时,代码没有接受处理程序的类型。

在您进行测试时,每个流都是逐个消息捕获的:仪表板一打开就显示捕获,然后每个消息都有其时间、事件名称和数据(像主体一样编辑),并且每个消息都根据其事件类型进行检查。 capture.maxMessages (200)和 capture.maxMessageBytes (64 kB)限制每个连接保留的内容。

尚

new WebSocket(url) 和socket . io的 io(url) 是请求站点。扫描列出了每个人发送和接收的消息及其类型: ws.send(JSON.stringify(subscribe)) 和 JSON.parse(e.data) as Quote 对于本机套接字, socket.emit('chat', draft) 和 socket.on('chat', (message) => ...) 套接字。IO类型的事件,例如 Socket<ServerEvents, ClientEvents> 两种都给)。

当您测试时,两个方向的每个消息都被捕获(像主体一样编辑),并使用封闭代码;套接字。IO事件按名称从它的帧中读取。仪表板显示发送和接收内容的时间轴,并根据其类型检查每条消息。 capture.maxMessages 和 capture.maxMessageBytes 限制每个连接保留的内容,如事件流。

详细设置

flow-checker init 显示它将改变什么,并首先询问:

  • instrumentation-client.ts (浏览器钩子)和 instrumentation.ts (服务器钩),旁边是你的 app 目录(在 src/ 当你使用 src/app). 如果 instrumentation.ts 已经出口 register(), init 添加流检查器块作为它的第一个语句(见下文)。服务器钩子还注册了一个小的边缘运行时,所以从边缘运行时的中间件发送的请求(middleware.ts 在Next.js 16之前)也被捕获;由0.1编写的Hooks可以从中获得它 init 或者 doctor.
  • flow-checker.config.ts.
  • .gitignore 捕获数据的条目。

两个钩子都是 无操作,除非应用程序是由流量检查器启动的 (FLOW_CHECKER=1),并且浏览器运行时在生产构建中永远不会处于活动状态,因此提交它们是安全的。

服务器钩子首先进入 register()

两个流量检查块必须是 的第一句 register(),在任何 if, register 必须 async:

// instrumentation.ts
export async function register() {
  // flow-checker: captures server-side requests while you test. It does nothing unless FLOW_CHECKER=1.
  if (process.env.FLOW_CHECKER === '1' && process.env.NEXT_RUNTIME === 'nodejs') {
    const { registerServerRuntime } = await import('@integr8-media/flow-checker/runtime/server')
    registerServerRuntime()
  }
  // flow-checker: requests sent from middleware on the edge runtime (fetch only, best effort).
  if (process.env.FLOW_CHECKER === '1' && process.env.NEXT_RUNTIME === 'edge') {
    const { registerEdgeRuntime } = await import('@integr8-media/flow-checker/runtime/edge')
    registerEdgeRuntime(process.env.FLOW_CHECKER_RUNTIME)
  }

  // your own code
  if (process.env.NODE_ENV === 'production') {
    // ...
  }
}

粘贴在现有条件中(例如仅用于生产的) if)或早睡后 return,他们从不跑下去 next dev,并且服务器端请求不会被静默地捕获。

  • init 编辑一个已有的 register() 对你来说:它把积木放在第一位,使 register async 需要时移动错位块时,再次运行。一个 register 从另一个文件重新导出后会得到一个注释,其中包含要添加的行。
  • doctor 对象中存在块时失败 if, switch、循环、 try三元, && 或嵌套回调,出现在其他代码之后,或当 register 不是 async. 它命名行并打印要移动的行。
  • dev 当钩子放错位置时,在开始时发出警告;当你的应用响应路由处理程序发送请求,但在10秒内没有捕获服务器端请求时,再次发出警告。Live显示了同样的警告。

flow-checker dev 以启动dev命令 FLOW_CHECKER=1, PORT 以及环境中的捕获设置。与 --no-app,它打印该环境,这样你就可以自己启动应用程序(例如在Docker容器或单线程任务运行器中)。

配置

可选的。一切都是自动检测的。看到 文档/ config.md 对于每个选项。

// flow-checker.config.ts
import { defineConfig } from '@integr8-media/flow-checker/config'

export default defineConfig({
  root: '.', // project root, relative to this file
  ports: { dashboard: 4400, app: 3000 },
  // Files the scan reads and skips (globs from the root). These are the defaults.
  include: ['**'],
  exclude: ['**/*.test.*', '**/*.spec.*', '**/*.stories.*', '**/__tests__/**', '**/__mocks__/**'],
  // Packages or modules whose calls are requests: HTTP libraries and API clients the scan
  // can't look inside. Default: none.
  apiClients: [{ module: 'ky', methods: ['default', 'get', 'post'] }],
  capture: {
    storeRaw: false, // true = save captures unmasked (local debugging only)
    redact: { keys: ['iban'], headers: ['x-session'] }, // added to the defaults
    ignore: ['/api/health'],
  },
  export: { md: 'docs/flow', html: '.flow-checker/site' },
  // A Postman collection to check the code against (v2.1 JSON, v3 YAML folder or { id, apiKeyEnv }).
  postman: { collection: 'postman/collections/My API', environment: 'postman/environments/dev.yaml' },
  // GraphQL types when the code has none: a schema file, or live introspection (env:NAME headers).
  graphql: { schema: 'schema.graphql' },
})

事件流和WebSocket捕获最多保留 capture.maxMessages 每个连接有200条消息,消息结束 capture.maxMessageBytes (64 kB),而不包含他们的数据。

敏感数据

修订是 默认开启 发生在运行时,在一个捕获离开你的应用程序之前:

  • 标题: authorization, cookie, set-cookie, x-api-key, proxy-authorization.
  • 任意深度的主体键(不区分大小写): password, pass, token, accessToken, refreshToken, secret, otp, code, cvv, cardNumber, ssn.
  • 类似jwt的值、承载令牌或卡号,以及敏感的查询参数。

遮罩值保持其形状("[REDACTED:string]", 0, false),所以类型检查仍然有效。工具服务器在到达时再次编辑,并再次导出编辑,除非您通过 --raw.

文件

.flow-checker/
├─ model.json          scan result (safe to commit)
├─ overrides.json      your decisions: manual matches, flow names, recordings (safe to commit)
├─ captures/           captured requests (gitignored)
├─ sessions/           browsing sessions used to confirm flows (gitignored)
├─ cache/              ingest token, code hashes, GraphQL introspection (gitignored)
└─ postman/            the last imported Postman collection (gitignored)

限制

  • 仅限应用路由器。
  • WebSockets:仅在浏览器中(不包括在服务器上打开的socket)。在模块级别(在它调用的组件或函数之外)创建的套接字不是请求站点。套接字。在连接移动到WebSocket之前,通过HTTP长轮询发送的消息不会被捕获(使用 transports: ['websocket'] 为了捕获所有内容,不记录ack,二进制附件不保留数据,并且在匹配时不区分名称空间。
  • 服务器发送的事件:EventSource只报告有人侦听的命名事件,因此应用程序没有侦听器的事件不会被记录。等库读取的事件流 @microsoft/fetch-event-source 被捕获(他们使用? fetch),但他们的听众不会被扫描出来。边缘运行时上的流被捕获为普通请求。
  • GraphQL: WebSockets上的订阅被捕获为WebSocket消息,但不链接到它们的操作。通过你自己的行动 fetch wrapper(不是Apollo、urql或Relay)是普通请求。服务器解析器不链接到运行它们的操作。
  • Edge运行时(Next.js 16之前的中间件):捕获是最好的努力, fetch 只有和没有传入请求。Node.js上的中间件(proxy.ts,或者 runtime: 'nodejs')像服务器的其他部分一样被捕获。
  • 中间件 config.matcher 必须在文件中写入(如Next.js所要求的);路由与动态段的样例值相匹配,对运行时构建的url的重定向或重写显示为写入的内容。
  • tRPC:通过调用的程序 createCaller 或者服务器端 createTRPCOptionsProxy({ router }) 在没有HTTP请求的情况下运行,并且不是请求站点。在代码中可以找到订阅,但它们的流被捕获为普通请求。路由器必须是可达的 fetchRequestHandler({ router }) 或者是客户的 AppRouter 类型。
  • 15.3之前的Next.js:浏览器捕获需要webpack(没有turbpack)和 withFlowChecker().
  • 大型存储库:第一次扫描约1800个文件的应用程序大约需要12秒,编辑后重新扫描大约需要4秒。重新扫描在工作线程中运行,因此仪表板和捕获同时保持响应。

许可证

麻省理工学院

版本与发布记录

@integr8-media/flow-checker 共发布 5 个版本,首次发布于 2026/10/30;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.2.2latest2026/11/012 天前
0.2.12026/10/312 天前
0.2.02026/10/313 天前
0.1.02026/10/304 天前
0.0.0-stage2026/10/304 天前

关于 @integr8-media/flow-checker 的常见问题

@integr8-media/flow-checker 是什么?

映射一个Next.js应用路由器项目:页面、组件、请求、类型和流,根据实时流量进行验证,并导出为文档。

如何安装 @integr8-media/flow-checker?

在项目目录运行 npm install @integr8-media/flow-checker,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 flow-checker,可以用 npx flow-checker 直接运行。

@integr8-media/flow-checker 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@integr8-media/flow-checker 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@integr8-media/flow-checker 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@integr8-media/flow-checker 可以商用吗?

@integr8-media/flow-checker 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@integr8-media/flow-checker 还在维护吗?

最新版本 0.2.2 发布于 2026/11/01(2 天前);至今共发布 5 个版本,其中过去 12 个月发布了 5 个;首次发布于 2026/10/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。