mcpField
C
codependix-configure

codependix-configure

github.com/organizzolini开发0291 次安装今天更新
代码仓库

关于 codependix-configure

用于配置 Nx 工作区中 Codependix 图导出和边界检查的技能,说明目标格式、项目选择、覆盖配置与校验规则。

主要功能

  1. 01设置图导出目标
  2. 02选择 JSON 或 Markdown 目标
  3. 03用 include 和 exclude glob 选择项目
  4. 04配置项目级图覆盖项
  5. 05定义图边界规则

适用场景

  1. 01为工作区项目设置导出
  2. 02将图写入 Markdown 锚点或文件
  3. 03从导出中排除项目
  4. 04添加边界检查依赖规则

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/organizzolini/codebase --skill codependix-configure

安装后在 Claude Code 中输入/codependix-configure确认已加载。

详细介绍

编写 codependix 配置

在配置告知 codependix 要导出什么以及导出到哪里之前,它不会生成任何内容。文件中的每个字段都是可选的,但配置文件本身不可省略:每次运行都必须通过 --config <path> 指定它(在此仓库中为 --config configuration/codependix.config.ts),未指定配置文件的运行会被拒绝。如果配置中省略 include,则每个项目的每种图类型都会解析为 target: "none"——运行成功,但不会写入任何内容。配置是唯一的控制入口;没有用于选择图类型的标志。

import { type CodependixConfiguration } from "@codependix/configuration";

const codependixConfiguration: CodependixConfiguration = {
  defaults: {
    imports: { markdown: { anchor: "codependix-file-imports" }, target: "markdown" },
    nestjs: { markdown: { anchor: "codependix-nestjs-modules" }, target: "markdown" },
    nx: { markdown: { anchor: "codependix-nx-projects" }, target: "markdown" },
  },
  exclude: ["fixtures/**"],
  include: ["**"],
  projects: {
    widgets: {
      nx: {
        json: { path: "output/nx-graph.json" },
        markdown: { anchor: "codependix-nx-projects", path: "docs/architecture.md" },
        target: "both",
      },
    },
  },
  workspace: {
    nx: { markdown: { anchor: "codependix-workspace" }, target: "markdown" },
  },
};

export default codependixConfiguration;

配置文件的查找位置

不会查找:配置文件必须明确指定。必须提供 --config <path>,没有默认文件名,不会搜索,也不会向上遍历,因此 codependix map --write --config configuration/codependix.config.ts 只会读取该文件,不会读取其他文件。 支持加载扩展名为 ts、mts、cts、js、mjs、cjs 或 json 的文件;不会改为读取旁边的其他文件。

  • 通过 --config 指定的路径必须存在。 路径拼写错误会导致运行失败,而不会悄悄将每种图都解析为 "none"。路径会先相对于当前工作目录解析,再相对于工作区根目录解析,因此配置文件若保存在 configuration/ 文件夹中,可以相对于任一位置指定。
  • 缺少 --config 也会导致运行失败。 此标志为必填项:省略时会报错并指出 --config,不会回退到工作区根目录下的 codependix.config.ts。

项目自己的 codependix.config.ts 是唯一会被查找而非指定的文件:它会从项目根目录旁读取,绝不会从父目录读取;没有此文件的项目不会生成项目级输出。

用 defaults,不要用 default

对没有自行指定覆盖项的所有项目生效的字段,名称是 defaults。加载配置模块时,会按名称解包其默认导出,因此名为 default 的字段会与解包操作冲突。使用 default: 的配置不会被拒绝——未知键会被移除,而不是拒绝,因此较新的配置在较旧版本的 codependix 中仍能加载——但它完全不起作用,看起来就像工具忽略了它。

target 必须明确指定

每种图类型的导出目标都必须明确命名,不会根据现有目标位置推断:

target写入内容
"both"同时写入 JSON 和 Markdown 目标位置
"json"仅写入 JSON 目标位置
"markdown"仅写入 Markdown 目标位置
"none"不写入任何内容——也是所有未设置目标的默认值

明确指定目标后,项目就可以保留尚未准备好写入的 json 目标位置:保留该目标位置,并设置 target: "markdown" 即可。

配置会经过验证,以下两种不匹配会被拒绝,而不是忽略:

  • 目标为 "both" 或 "json",但未指定 json 目标位置。
  • 目标为 "both" 或 "markdown",但未指定 markdown 目标位置。

Markdown 有两种形式

// Anchor mode — spliced into a named block inside an existing file.
{ markdown: { anchor: "codependix-nx-projects" }, target: "markdown" }

// Anchor mode, in a file other than the default README.md.
{ markdown: { anchor: "codependix-nx-projects", path: "docs/graphs.md" }, target: "markdown" }

// Standalone mode — the export is the whole contents of the file.
{ markdown: { path: "output/graph.md" }, target: "markdown" }
  • 指定 anchor 会将导出内容插入 path 指定文件中的两个注释标记之间;path 默认为 README.md——通常使用项目自己的 readme,因此无需重复指定。
  • 不设置 anchor 会将导出内容写成独立文件的全部内容,此时必须指定 path:对于由 codependix 完全管理的文件,没有值得猜测的默认路径。
  • 如果 markdown 目标位置两者都没有指定,则会被拒绝,因为没有位置可以写入导出内容。

运行 --write 时会自动创建缺失的锚点区块,因此无需事先手动放置锚点。有关新建区块的具体位置以及仍会导致失败的情况,请参阅 codependix-triage skill。

这两种目标位置中的路径都相对于项目自身的根目录解析,因此一条 defaults 条目就能描述所有项目,无需逐一命名。整个工作区的图则相对于工作区根目录解析。

include 和 exclude

两者都是 glob 列表,会与项目的 Nx 名称及其相对于工作区的根目录匹配,因此两种写法都有效:

{ exclude: ["examples/**", "*-fixtures"], include: ["**"] }

include 默认为不包含任何内容,exclude 默认为空,因此两者都省略时,没有项目会参与运行,也不会导出任何内容。必须明确声明参与范围:使用 include: ["**"] 可覆盖整个工作区。当至少一个 include glob 命中项目名称或根目录,且没有 exclude glob 命中任一项时,该项目才会被纳入。

--projects 和 --tags 可从命令行扩大此范围——只要项目名称出现在其中任一列表中,即使没有 include glob 命中,该项目也会参与;而 exclude 仍优先于两者。参见 codependix-export。

配置中指定了 defaults 却没有 include,是需要特别留意的情况。此时不会导出任何内容,但进程仍会以状态码 0 退出;而 --check boundaries 会检查所有项目,不受 include 限制——也不受 --projects 和 --tags 指定的项目限制——因此检查仍会通过。发生这种情况时,导出运行会发出警告——🕸️ Selected no project to export。

无论 defaults 或项目自身的 projects 条目如何设置,被排除的项目对所有图类型都会解析为 target: "none"——因此,排除一个项目只需一行,无需把它的每个覆盖项都改写为 "none"。

项目覆盖会替换,而不会合并

当 projects 条目指定某种图类型时,该条目会直接替换该图类型对应的 defaults 条目,而不是逐字段合并。项目关闭 Markdown 导出时,若省略 markdown,默认配置中的 markdown 目标不应重新生效。

实际使用中,覆盖项必须重新声明所有仍需要的目标,包括 target。

{
  defaults: { nx: { markdown: { anchor: "codependix-nx-projects" }, target: "markdown" } },
  projects: {
    // Loses the Markdown export entirely — this is the whole nx entry now.
    widgets: { nx: { json: { path: "graph.json" }, target: "json" } },
    // Keeps both, because both are restated.
    gadgets: {
      nx: {
        json: { path: "graph.json" },
        markdown: { anchor: "codependix-nx-projects" },
        target: "both",
      },
    },
  },
}

覆盖项未提及的图类型仍会回退到 defaults;替换是按图类型进行的,而非按项目进行的。

整个工作区的图

workspace 与 defaults 和 projects 相互独立,且仅接受 nx:

{ workspace: { nx: { markdown: { anchor: "codependix-workspace" }, target: "markdown" } } }

没有适用于整个工作区的 NestJS 图或导入图。工作区图会为整个仓库导出一次,不支持按项目覆盖,且不受 include 和 exclude 影响——从按项目导出中排除某个项目,不会将其从工作区图中移除。

--projects 和 --tags 是例外,它们通过图的节点集合影响工作区图,而不是通过导出目标影响它:运行时指定选择范围后,图会基于所选项目绘制,并写入 workspace.nx 指定的位置。有关这两个标志,请参见 codependix-export。

projectGraph——读取图,而非解析图

{ projectGraph: "artifacts/graph.json" }

相对于工作区根目录的路径,指向 nx graph --file=graph.json 输出的 JSON 文件。指定该项后,会读取此文件,而不是解析进程当前工作目录自身的图——这是为进程所在目录之外的工作区绘制图的唯一方式。省略该项则不会改变任何行为。

该文件会被信任:只有完全不是项目图的文件才会被拒绝。此行为的适用范围,请参见 codependix-export。

配置项目不具备的图类型不会产生任何成本

非 NestJS 项目不会出现在 NestJS 处理阶段;没有 tsconfig.json 的项目不会出现在 TypeScript 导入处理阶段。这两种情况都不算失败,也不需要覆盖配置,因此,在整个工作区的配置中,用一个 defaults 块指定全部四种图类型是常见做法,并不算范围过宽。

boundaries — 评判图的规则

defaults 和 projects 指定导出内容写入的位置。boundaries 指定图必须呈现的样子,按相同的四个图级别进行配置;它由 --check boundaries 控制,而非 --check reports。

const codependixConfiguration: CodependixConfiguration = {
  boundaries: {
    imports: [
      {
        from: { path: ["**/*.types.ts"] },
        kind: "forbid",
        message: "Types are the leaf of a module.",
        name: "types-files-do-not-reach-services",
        to: { path: ["**/*.service.ts"] },
      },
    ],
    nx: [
      {
        from: { tags: ["type:application"] },
        kind: "forbid",
        name: "applications-are-leaves",
        to: { tags: ["type:application"] },
      },
      { kind: "acyclic", name: "no-project-cycles" },
    ],
  },
};

三种类型:

类型说明
forbid源匹配 from 且目标匹配 to 的边
allow离开 from、且目标不在 to 声明范围内的边
acyclicnodes 选中的节点之间不能有环;默认选择所有节点

选择器的四个字段都是 glob 列表,并且会彼此收窄——选择器指定的每个字段都必须匹配,而在同一字段中,只需匹配一个 glob:

字段匹配对象所属级别
id节点标识符——项目名、文件路径或模块类名所有级别
path相对于工作区的项目根目录,或相对于项目的文件路径nx、imports、pythonImports
project节点所属的 Nx 项目nx、imports、pythonImports
tags节点的 Nx 标签;只需匹配一个标签nx

访问规则还可以用 edges 收窄其评判的边: { implicit: false } 仅查看有导入语句作为依据的边——与 @nx/enforce-module-boundaries 的 depConstraint 完全相同;{ implicit: true } 仅查看由 implicitDependencies 条目声明的边。未设置时,两者都会评判,这是更严格的解读。只有 Nx 级别会绘制隐式边。

编写规则前需要了解四点:

  • 选择器指定了其所属级别不包含的字段时,将匹配不到任何内容,而非匹配所有内容。在 nestjs 级别使用 path 规则不会选中任何模块,因为 NestJS 模块图只包含类名,完全没有文件路径。
  • 未指定任何字段的选择器会被 schema 拒绝。这看起来就像拼写错误;若将其解读为“所有节点”,规则范围就会在不知不觉中扩大到整个工作区。
  • **message 会追加到生成的句子后,而不是取代它。**请将其写成_原因_;内容——规则名称和两个端点——始终由系统生成。
  • **没有规则的级别绝不会构建。**声明 nestjs 规则意味着每个容器都会以预览模式启动;声明 imports 规则意味着每个项目都会创建一个 ts.Program。只声明你实际要设为门禁的级别。

**编写已经满足的规则。**一开始就失败的规则只会成为待办事项,而无人能采取行动的失败流水线只会让人学会忽略它。提交候选规则前,请先针对整个工作区验证。

哪个项目会因发现的问题而失败

发现的问题会归到项目名下;只有被评判的项目被计入问题时,本次运行才会失败。问题类型决定归属:

发现的问题计入对象
匹配 forbid,或没有任何 allow 规则覆盖的边拥有该边源的项目,不计入其他项目
acyclic 环拥有环上节点的每个项目,因此跨越 A 和 B 的环会使两者都失败
无法启动的容器容器启动失败的项目;如果失败类属于另一个项目,则会注明该类的所有者

如果某项目只是依赖了存在环或禁止边的项目,它不会失败:它只会将该发现视为一条注释,标记为“在依赖项中”。因此,编写规则时要考虑源项目——必须做出修改的正是该项目。无法启动的容器是个例外:如果某个依赖项中的类无法求值,导致依赖它的项目自身容器启动失败,那么该项目也会失败,因为它的容器确实无法启动;失败信息会注明该依赖项的所有者。

每个项目的 gate

在 Nx 工作区中,@codependix/nx 插件会为每个由 project.json 描述的项目推断一个 codependix-gate 目标,工作区根目录除外。它会在该项目及其依赖项上运行 --check boundaries --projects <project>。对于 Nx 仅从 package.json 推断出的项目,在为其提供 project.json 之前,不会有 gate。在 nx.json 中注册一次插件:

{
  "plugins": [
    {
      "plugin": "@codependix/nx",
      "options": {
        "configurationPath": "configuration/codependix.config.ts",
        "gateTargetName": "codependix-gate"
      }
    }
  ]
}

configurationPath 指定所有 gate 都会读取的唯一配置文件,且为必填项:不带此选项的注册会失败,并报错指出该选项;也不会假定工作区根目录下存在 codependix.config.ts。gate 目标可以通过执行器选项 configuration 覆盖此项(不是 Nx 自身的 --configuration 标志,后者用于选择 check 或 write);若值为空则会拒绝,并指出该选项。每个项目不会配置其他内容:boundaries 中的规则会以相同方式评判每个项目。有关如何运行 gate,请参阅 codependix-export。

gate 会在插件自行注册的 @swc-node/register 钩子下运行命令行,因此工作区无需为这些钩子安装任何内容。工作区根目录确实需要一个会生成装饰器元数据的 tsconfig.json,因为这些钩子会从工作目录读取它,而且 NestJS 构造函数注入依赖该元数据。

gate 会进行缓存。项目自身的 codependix.config.* 是其缓存输入之一,因此编辑该文件会重新运行该 gate。codependix 命令行本身也是缓存输入:如果它是工作区中的一个包,则包括其 package.json 和源代码;如果它来自注册表,则包括其安装版本。工作区根目录的 tsconfig.json 也是缓存输入,加载器会读取它。测试文件不是输入,因此只修改工具的测试,不会使该包自身及其依赖项以外的 gate 失效;其他任何修改都会使所有 gate 重新运行。如果插件无法解析某个包,则只有该包自身的输入会丢失,Nx 的日志记录器会发出警告并指出该包。

如果某个 gate 的 projects 或 tags 选择了自身项目以外的任何内容(无论是在命令行、目标选项中,还是在命名的 Nx 配置中),都不会从缓存中重放,因为它评判的项目不在其输入覆盖范围内。只评判自身项目的 gate 会照常缓存。

评论

支持 Markdown