- 开发工具
- 静态分析
- 代码质量
【免费下载链接】dependency-cruiser
Validate and visualize dependencies. Your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.
本篇技术指南聚焦 dependency-cruiser 仓库中的src/schema/目录,讲解其 JSON Schema(配置 Schema 与巡航结果 Schema)如何由tools/schema/下的源定义生成、如何通过 Ajv 编译成独立校验器,以及这些校验器如何在 CLI 运行时与格式化阶段被真实调用。读完本文,你将掌握该项目的 Schema 生成脚本、Makefile 自动化规则、产物形态与运行时消费链路,并能独立完成"修改 Schema 定义 → 重新生成 → 验证生效"的完整操作。
一、src/schema/README.md说了什么:一条"源定义 → 生成产物"的工作流
仓库根目录下的 src/schema/README.md 用极简的篇幅定义了本目录的维护纪律,是理解整个 Schema 体系的入口:
src/schema/下的 JSON Schema 文件由tools/generate-schemas.utl.mjs脚本生成;- 其中的校验器文件由
tools/generate-schema-validator.utl.mjs脚本生成; - 如果需要对 Schema 做修改,不要直接编辑
src/schema/下的生成产物,而是修改 tools/schema/ 中的源定义; - 修改之后重新运行生成脚本,既可以执行
make,也可以分别运行node tools/generate-schemas.utl.mjs与node tools/generate-schema-validator.utl.mjs。
这条规则意味着src/schema/是一个"生成目录",它的内容全部是机器产物;而tools/schema/才是人工维护的"单一事实来源"(Single Source of Truth)。
二、单一事实来源:tools/schema/下的 Schema 源定义
tools/schema/目录以 ES Module(.mjs)形式组织 Schema 定义,共约三十个模块,按职责可分为几组:
- 顶层配置组合:
configuration.schema.mjs、cruise-result.schema.mjs、baseline-violations.schema.mjs; - 规则集定义:
rule-set.mjs(forbidden/allowed/allowedSeverity/required)、restrictions.mjs(from/to等约束类型)、severity-type.mjs; - 巡航选项定义:
options.mjs、cache-options.mjs、compound-*-type.mjs(doNotFollow、exclude、includeOnly、focus、highlight、reaches等复合类型)、module-systems-type.mjs、output-type.mjs、reporter-options.mjs、experimental-stats-type.mjs; - 巡航结果结构:
modules.mjs、dependencies.mjs、dependency-type.mjs、mini-dependency-type.mjs、folders.mjs、summary.mjs、violations.mjs、violation-type.mjs、rule-summary.mjs、revision-data.mjs、options-used.mjs等。
以 tools/schema/configuration.schema.mjs 为例,顶层配置 Schema 通过模块组合完成:properties直接展开ruleSet.properties,再追加options与extends两个引用;definitions则合并ruleSet.definitions、options.definitions与自定义的ExtendsType(支持单个字符串或字符串数组,表示该配置所继承的基配置)。ruleSet.properties则由 tools/schema/rule-set.mjs 提供:forbidden(禁止的依赖规则)、allowed(允许的依赖规则,违反时输出not-in-allowed警告)、allowedSeverity(not-in-allowed的严重级别,默认warn)与required(模块必须具备的依赖,例如每个 controller 必须直接依赖 base controller)。所有规则类型均设置additionalProperties: false,杜绝未知字段静默通过。
三、三种产物形态:.schema.json、.schema.mjs与.validate.mjs
生成脚本会产出三种文件,各自承担不同角色:
| 产物 | 示例 | 用途 |
|---|---|---|
| 可读 JSON Schema | src/schema/configuration.schema.json | 面向人阅读、IDE 提示与外部工具(如编辑器基于$schema做自动补全) |
| 紧凑 ESM Schema | src/schema/configuration.schema.mjs(中间产物,Makefile 会在校验器生成后清理) | 供生成校验器时以 JS 模块形式被import |
| 独立校验器 | src/schema/configuration.validate.mjs、src/schema/cruise-result.validate.mjs | 运行时被 CLI 直接调用,校验配置与巡航结果 |
其中 src/schema/configuration.schema.json 声明了$id: https://dependency-cruiser.js.org/schema/configuration.schema.json,顶层properties仅允许$schema、forbidden、allowed、allowedSeverity、required、options、extends七个键,并整体设置additionalProperties: false。
四、生成脚本剖析:tools/generate-schemas.utl.mjs
src/schema/README.md 指定的第一个生成脚本是 tools/generate-schemas.utl.mjs,其关键行为如下:
1. 按目标文件扩展名分派输出格式
emitConsolidatedSchema(pOutputFileName)依据扩展名决定产物形态:
- 目标是
.json时:用 prettier 的jsonparser 对JSON.stringify(schema.default)做格式化后写入; - 目标是
.mjs时:先通过stripAttribute递归删除所有description字段(减小体积),拼装成/* generated - don't edit */ export default {...}形式的 ESM 模块,再用 prettier 的 babel parser 格式化、最后经@babel/core的transformSync(..., { minified: true })压缩后写入。
2. 通过正则推导输入模块名
getInputModuleName(pOutputFileName)从输出路径(如./src/schema/configuration.schema.json)反推输入源定义(./configuration.schema.mjs),即tools/schema/下同名.schema.mjs模块。
3. 强制 Node 权限模型
脚本开头检查process.permission,并要求在 Node 的 Permission Model(--permission)下运行,随后尝试drop对..与/的读写权限,缩小脚本自身的能力边界。用法为:
node tools/generate-schemas.utl.mjs ./src/schema/configuration.schema.json五、校验器生成剖析:tools/generate-schema-validator.utl.mjs
src/schema/README.md 指定的第二个脚本是 tools/generate-schema-validator.utl.mjs。它基于 Ajv 的 standalone 代码生成能力:
- 用
new Ajv({ code: { source: true, esm: true } })创建编译器实例(产出 ESM 形态的源码级校验代码); import输入的.schema.mjs并ajv.compile(schema.default);- 调用
standaloneCode(ajv, validate)把编译结果导出为不依赖 Ajv 运行时的独立模块,写入输出文件。
用法(脚本自带 Usage 示例):
node tools/generate-schema-validator.utl.mjs ./src/schema/configuration.schema.mjs ./src/schema/configuration.validate.mjs生成出的 src/schema/configuration.validate.mjs 是压缩后的 ESM:开头即export const validate=de;export default de;,全部校验逻辑内联为普通函数(如对SeverityType的["error","warn","info","ignore"]枚举、对dependencyTypes的约四十个枚举值的逐项检查、对additionalProperties的键白名单检查等),可被任何 ESM 环境直接 import 使用。
六、Makefile 自动化:make build一键重建
Makefile 将上述两步脚本编排成 make 规则,README 中"重新运行生成脚本(either by runningmake...)"指的就是这套自动化:
build目标依赖三组文件:GENERATED_SOURCES(baseline-violations.schema.mjs/json、configuration.schema.json、cruise-result.schema.json、src/meta.cjs)、GENERATED_VALIDATORS(两个.validate.mjs);- 生产规则
src/%.schema.mjs: tools/%.schema.mjs $(SCHEMA_SOURCES) tools/generate-schemas.utl.mjs与同款.json规则,把tools/schema/源定义连同全部SCHEMA_SOURCES一起作为依赖,用$(NODE) --allow-fs-read ./ --allow-fs-write ./src/schema/执行生成脚本(这里的--permission正是脚本内部检查所要求的); - 生产规则
src/schema/%.validate.mjs: src/schema/%.schema.mjs tools/generate-schema-validator.utl.mjs先生成未压缩校验器,随后npx esbuild --tree-shaking=true --minify二次压缩,最后$(RM) $<删除作为中间产物的.schema.mjs(所以在最终仓库里只见.schema.json与.validate.mjs); clean目标删除全部生成产物,help目标说明build与clean的用途。
七、运行时消费链路:校验器在 CLI 与格式化阶段被真实调用
生成的校验器并非摆设,而是贯穿 dependency-cruiser 主流程的硬性检查:
- 配置校验:src/main/rule-set/assert-validity.mjs 导入
#schema/configuration.validate.mjs,在assertSchemaCompliance中调用validateConfigurationSchema(pConfiguration),校验失败即抛出The supplied configuration is not valid: ...并附上错误详情——这意味着任何非法配置在巡航开始前就会被拒绝; - 结果校验:src/main/format.mjs 导入
#schema/cruise-result.validate.mjs,在格式化输出前用validateCruiseResultSchema(pResult)校验巡航结果,失败抛出The supplied dependency-cruiser result is not valid: ...; - 错误格式化:src/schema/utl.mjs 提供
validateErrorsToString(pErrors),把 Ajv 错误数组(instancePath+message)拼接成可读字符串,供上述两处抛错使用。
由此可以确认一条完整链路:开发者修改tools/schema/源定义 →make build或两个node脚本重新生成src/schema/产物 → CLI 运行时经assert-validity.mjs用新校验器拦截非法配置。
八、实践指引:修改 Schema 的标准操作流程
结合 src/schema/README.md 的约定与上述源码证据,为 dependency-cruiser 扩展配置项的推荐流程是:
- 改源定义:在 tools/schema/ 中编辑对应的
.schema.mjs(新增配置项时通常涉及options.mjs及其引用类型模块); - 重新生成:在仓库根目录执行
make build;若只想重建单个文件,可按 README 给出的命令分别执行node tools/generate-schemas.utl.mjs与node tools/generate-schema-validator.utl.mjs(注意脚本需要 Node 的--permission模式,直接运行请参照 Makefile 中的$(NODE)定义补齐权限参数); - 验证生效:编写带新字段的
.dependency-cruiser.cjs配置运行depcruise,确认不再触发assertSchemaCompliance的抛错,且旧配置仍可通过校验(回归); - 保持纪律:绝不手工编辑
src/schema/下的生成产物——它们带有生成标记或被压缩,手工改动会在下次make build时被覆盖。
对使用 dependency-cruiser 的普通用户而言,同样能从这套体系受益:在配置文件中声明"$schema": "https://dependency-cruiser.js.org/schema/configuration.schema.json",编辑器即可基于仓库公开的 Schema 提供配置键补全与非法字段提示,把大部分配置错误消灭在编写阶段,而不是等到 CLI 运行时才收到The supplied configuration is not valid的报错。
- 开发工具
- 静态分析
- 代码质量
【免费下载链接】dependency-cruiser
Validate and visualize dependencies. Your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.
相关推荐
oh-my-openagent 的生成式 Schema 制品体系:从 Zod 到 JSON Schema 的单一事实来源流水线
oh my openagent 的生成式 Schema 制品体系:从 Zod 到 JSON Schema 的单一事实来源流水线 assets/ 目录是 oh m
人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排OmO 配置体系中的 telemetry 配置项:从 Zod 严格校验到统一 Schema 生成的全链路实现
OmO 配置体系中的 telemetry 配置项:从 Zod 严格校验到统一 Schema 生成的全链路实现 导读 本文基于 oh my openagent 仓
人工智能AI Agent代码智能体多智能体MCP ClientsAgent 编排Relay 开发工作流:从配置 Relay Compiler 到生成运行时产物
Relay 开发工作流:从配置 Relay Compiler 到生成运行时产物 本篇技术指南以 Relay v14 文档中的 Workflow 章节为核心,讲解
前端开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考