1
0

refactor: 移除顶层 defaults 配置段,简化为 target 显式字段 > 代码内置默认值

- 移除 DefaultsConfig 类型、ProbeConfig.defaults 字段
- 移除 CheckerSchemas.defaults、ResolveContext.defaults、CheckerValidationInput.defaults
- 更新所有 checker schema/resolve/validate 删除 defaults 合并逻辑
- 更新 config-loader 不再读取传递 defaults
- 更新测试、README、DEVELOPMENT、probes.example.yaml
- 重新生成 probe-config.schema.json(不含 defaults)
- 同步 delta specs 到主规范
- 归档 openspec change
This commit is contained in:
2026-05-21 16:53:12 +08:00
parent e448cb4654
commit 79358ba50d
52 changed files with 196 additions and 940 deletions

View File

@@ -64,7 +64,7 @@ src/
metrics.ts GET /api/targets/:id/metrics
history.ts GET /api/targets/:id/history
checker/
types.ts 基础类型定义ResolvedTargetBase、RawTargetConfig、DefaultsConfig、CheckResult 等基础 interface
types.ts 基础类型定义ResolvedTargetBase、RawTargetConfig、CheckResult 等基础 interface
config-loader.ts YAML 配置解析、契约校验、语义校验与运行期解析(输出 ResolvedConfig
variables.ts 配置 variables 提取、target 字符串变量替换和 unresolved-variable issue 生成
schema/ TypeBox + Ajv 配置契约、schema fragments、issue 渲染和 schema 导出入口
@@ -237,7 +237,7 @@ export function handleMetrics(idStr: string, url: URL, store: ProbeStore, mode:
- **后端内部扩展**`checker/types.ts``CheckResult` 通过 `extends` 共享版本的 `ApiCheckResult` 增加 `targetId` 等内部字段
- 存储层类型(`StoredTarget``StoredCheckResult`)独立定义,与 API 类型分离
- **Checker 类型分层**
- `checker/types.ts` 定义 base interface`ResolvedTargetBase``RawTargetConfig``DefaultsConfig`),使用 index signature 支持扩展
- `checker/types.ts` 定义 base interface`ResolvedTargetBase``RawTargetConfig`),使用 index signature 支持扩展
- 各 checker 在自己的 `types.ts` 中定义具体类型(如 `ResolvedHttpTarget``ResolvedCommandTarget`),满足 base interface 约束
- 中间层engine、store、config-loader只依赖 base interface不感知具体 checker 类型
- `CheckerDefinition<TResolved extends ResolvedTargetBase = ResolvedTargetBase>` 使用泛型约束 `resolve` 返回值以及 `execute``serialize` 的 target 参数
@@ -267,9 +267,9 @@ export function handleMetrics(idStr: string, url: URL, store: ProbeStore, mode:
契约层使用 `src/server/checker/schema/` 中的 TypeBox fragments 生成 JSON Schema并用 Ajv 执行启动期校验。Ajv 必须保持严格拒绝模式:`allErrors: true`、不启用类型强制转换、不注入默认值、不自动删除未知字段。
默认对象策略是 `additionalProperties: false`。只有明确声明的动态键值表可以开放任意键名,例如 `variables``http.headers``defaults.http.headers``expect.headers``cmd.env`
默认对象策略是 `additionalProperties: false`。只有明确声明的动态键值表可以开放任意键名,例如 `variables``http.headers``expect.headers``cmd.env`
契约校验和语义 validator 都必须返回 `ConfigValidationIssue[]`,不要在 validator 内直接拼接最终用户错误字符串。最终错误由 `formatConfigIssues()` 统一渲染,错误路径需要尽量包含 `targetName``defaults`/root 路径。
契约校验和语义 validator 都必须返回 `ConfigValidationIssue[]`,不要在 validator 内直接拼接最终用户错误字符串。最终错误由 `formatConfigIssues()` 统一渲染,错误路径需要尽量包含 `targetName` 或 root 路径。
新增或修改配置字段时必须同步更新TypeBox schema fragments、`probe-config.schema.json` 导出、对应语义 validator、单元测试和 README/DEVELOPMENT 用户文档。提交前运行 `bun run schema:check` 确认导出 schema 与 fragments 一致。
@@ -303,7 +303,7 @@ checkerRegistry单例
| ------------- | ------------------------------------------------------------------------------------------ |
| `index.ts` | 模块入口re-export Checker 类 |
| `types.ts` | Checker 专属类型RawXxxTargetConfig、Raw/Resolved XxxExpectConfig、ResolvedXxxTarget 等) |
| `schema.ts` | TypeBox 契约 schemaconfig / defaults / expect 部分) |
| `schema.ts` | TypeBox 契约 schemaconfig / expect 部分) |
| `validate.ts` | 启动期语义校验JSON Schema 无法表达的规则) |
| `execute.ts` | Checker 类resolve默认值合并 + 解析、execute执行检查、serializeDB 持久化) |
| `expect.ts` | Checker 专用断言函数 |
@@ -315,14 +315,13 @@ checkerRegistry单例
- `RawXxxTargetConfig` — YAML 原始配置类型
- `RawXxxExpectConfig` / `ResolvedXxxExpectConfig` — Raw expect 字段类型与运行期 Resolved expect 执行计划类型
- `XxxDefaultsConfig` — defaults 专属字段类型
- `ResolvedXxxTarget extends ResolvedTargetBase` — resolve 后的完整类型,含 `type: "xxx"` 字面量
**注意**:不需要修改顶层 `checker/types.ts`。base interface 使用 index signature`[key: string]: unknown`checker 专属类型通过 `extends ResolvedTargetBase` 自动兼容。
#### 1.7.3 步骤二:创建 TypeBox 契约 Schema
`src/server/checker/runner/tcp/schema.ts` 中定义 `CheckerSchemas`config / defaults / expect 部分)。参考 `http/schema.ts``cmd/schema.ts`,使用 `schema/fragments.ts` 中的共享片段。
`src/server/checker/runner/tcp/schema.ts` 中定义 `CheckerSchemas`config / expect 部分)。参考 `http/schema.ts``cmd/schema.ts`,使用 `schema/fragments.ts` 中的共享片段。
**可复用的共享 fragments**(来自 `schema/fragments.ts`
@@ -368,17 +367,16 @@ TcpChecker implements Checker
readonly schemas ← tcpCheckerSchemas
validate(input) ← 调用 validateTcpConfig(input)
resolve(target, ctx)← 默认值合并 + 解析,返回 satisfies ResolvedTcpTarget
resolve(target, ctx)← 内置默认值填充 + 解析,返回 satisfies ResolvedTcpTarget
execute(target, ctx)← 执行检查,返回 CheckResult
serialize(target) ← 返回 { config, target } 用于 DB 持久化
```
**`resolve()` 规范**
- 只做默认值合并、路径解析、单位转换,**不执行校验**
- 只做内置默认值填充、路径解析、单位转换,**不执行校验**
- 若 checker 支持 expect必须保留 `rawExpect` 为变量替换后的 Raw 配置快照,并生成只供 `execute()` 使用的 Resolved `expect`
- 返回 `satisfies ResolvedXxxTarget` 确保类型正确
- 通过 `context.defaults[this.configKey]` 访问 checker 专属默认值(需 `as` 断言为具体类型)
**expect 五层管线**:每种断言模型从定义到执行经过五个阶段,每层使用对应的共享函数:
@@ -457,13 +455,13 @@ if (r.body) {
注册后,以下管线会通过 registry 自动委托,**无需新增 type 分支**
| 模块 | 自动行为 |
| -------------------- | ------------------------------------------------------------------------ |
| `schema/builder.ts` | 遍历 registry 生成全量 JSON Schemadefaults.tcp + target.tcp + expect |
| `schema/validate.ts` | 按注册 checker 构建 Ajv 校验,自动识别 `type: tcp` |
| `config-loader.ts` | 遍历 registry 调用每个 checker 的 `validate()` + `resolve()` |
| `engine.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `execute()` |
| `store.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `serialize()` |
| 模块 | 自动行为 |
| -------------------- | -------------------------------------------------------------- |
| `schema/builder.ts` | 遍历 registry 生成全量 JSON Schematarget.tcp + expect |
| `schema/validate.ts` | 按注册 checker 构建 Ajv 校验,自动识别 `type: tcp` |
| `config-loader.ts` | 遍历 registry 调用每个 checker 的 `validate()` + `resolve()` |
| `engine.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `execute()` |
| `store.ts` | 按 `target.type` 从 registry 取对应 checker 执行 `serialize()` |
注意:自动适配指上述中间层不需要新增 `switch/case` 或类型分支;开发者仍需按后续步骤更新配置示例、文档和测试。