setup-ts-deep-modules
将 dependency-cruiser 接入 TypeScript 仓库,使每个 package 成为深层模块,实现代码隐藏在子文件夹中,只能通过其入口文件访问。由用户主动调用。
技能说明mattpocock/skills
将 dependency-cruiser 接入 TypeScript 仓库,使每个 package 成为深层模块,实现代码隐藏在子文件夹中,只能通过其入口文件访问。由用户主动调用。
技能简介
本技能将 dependency-cruiser 接入 TypeScript 仓库,强制每个 package 成为“深层模块”:实现代码隐藏在各 package 的子文件夹中,外部代码只能通过该 package 的入口文件(根目录文件)访问。它帮你治理大型 TS 仓库的跨包依赖边界,防止深层导入和循环依赖。
使用场景
- 多包 TypeScript 仓库中,规范各个 package 之间的依赖边界
- 防止业务代码或测试代码绕过入口文件、直接深入导入其他包的内部实现
- 让每个 package 形成“小接口、大实现”的结构,便于重构与长期维护
- 落实“测试只通过入口文件访问”的架构约定,保证集成测试合法、深层导入不可能
- 作为团队规范落地工具,让架构约束通过 CLI 自动检查,而不是靠 code review
使用方法
本技能由用户主动调用,执行步骤如下(以 pnpm 为例,实际可替换为 yarn/npm/bunx):
-
检测环境:确认包管理器(
pnpm-lock.yaml→ pnpm,yarn.lock→ yarn,bun.lockb→ bun,否则 npm)。确认 packages 根目录(存在src/则用src/packages,否则用packages)。若已有.dependency-cruiser.*配置,不要覆盖,需合并。 -
安装依赖:将
dependency-cruiser安装为 devDependency。pnpm add -D dependency-cruiser -
写入配置:将
dependency-cruiser.config.cjs复制为仓库根目录下的.dependency-cruiser.cjs,并设置PACKAGES_ROOT为检测到的根目录。规则基于路径深度,无需其他适配。 -
接入检查流程:添加
lint:boundaries脚本:depcruise src # 或 depcruise packages将
lint:boundaries并入仓库现有的总检查命令(与 typecheck 在同一命令中运行)。不要修改tsconfig,不要添加路径别名。 -
搭建示例包:在
<packages-root>/example/创建可复制模板,包含入口index.ts、子目录实现lib/impl.ts、测试tests/example.test.ts(只从../index导入)。 -
验证规则生效:先运行
lint:boundaries,应通过;在测试里临时添加深层导入(如import { thing } from "../lib/impl"),再运行应 失败;撤销该导入后应再次通过。 -
记录约定:在 packages 根目录写
README.md,说明目录布局和“只能通过入口文件导入”的约定。
注意事项
- 入口文件 ≠ 单一 index.ts。每个根目录文件都是入口,包可以暴露多个小入口(如
index.ts、client.ts、server.ts);不要用 barrel 文件把整个子树重新导出。 - 已有 dependency-cruiser 配置时 不要覆盖,而是合并规则并告知用户新增内容。
- 包与包之间的分层依赖(如 core 与 feature 的上下层关系)是独立关注点,配置中留有注释占位,由仓库自行补充。
- 技能完成标准是“规则咬得住”:必须观察到对深层导入的导入会失败,否则视为未正确接线,需修复后再结束。
- 无 umbrella check 脚本时,
lint:boundaries需由用户手动加入 CI。