feat: 引入分层配置生命周期,支持变量引用和 JSON Schema 校验
- 新增 src/server/config/ 模块(types、issues、variables、normalizer、schema)
- 配置布局从 server.host/server.port 切换为 server.listen.host/server.listen.port
- 移除 HOST/PORT 隐式环境变量覆盖,改为 YAML 显式 ${KEY} 变量引用
- 支持 ${KEY}、${KEY|default}、${KEY|}、$${KEY} 变量语法
- 使用 @sinclair/typebox + ajv 实现运行时严格契约校验和 JSON Schema 导出
- 新增 scripts/generate-config-schema.ts 和 config.schema.json
- 新增 bun run schema / schema:check 命令,check 先执行 schema:check
- 更新 README.md 和 DEVELOPMENT.md 匹配新配置体系
- 新增变量解析、schema 校验和 schema 同步测试
This commit is contained in:
@@ -23,7 +23,8 @@ my-app 开发文档
|
||||
src/
|
||||
server/
|
||||
bootstrap.ts 后端统一启动引导(loadServerConfig → startServer)
|
||||
config.ts CLI 参数解析与配置文件加载(可选 YAML configPath,支持 --help/-h)
|
||||
config.ts CLI 参数解析与配置文件加载 facade(可选 YAML configPath,支持 --help/-h)
|
||||
config/ 配置解析模块(types、issues、variables、normalizer、schema)
|
||||
dev.ts 开发模式启动入口(mode: "development")
|
||||
main.ts 生产模式启动入口(mode: "production",安全头启用)
|
||||
server.ts HTTP server 启动工厂(Bun.serve routes 声明式路由 + fetch fallback 静态资源服务)
|
||||
@@ -63,10 +64,11 @@ src/
|
||||
time.ts 时间处理(formatCountdown、formatDurationUnit、formatRelativeTime、isOlderThan、subtractHours)
|
||||
menu.tsx 菜单配置(路由与菜单项统一数据源)
|
||||
routes.tsx 路由配置(定义所有页面路由)
|
||||
scripts/
|
||||
dev.ts 双进程开发服务(Bun API server + Vite dev server)
|
||||
build.ts Vite → codegen → Bun compile 三步构建流水线(含版本号注入)
|
||||
bump-version-logic.ts 纯版本管理逻辑(parse、validate、bump、format)
|
||||
scripts/
|
||||
dev.ts 双进程开发服务(Bun API server + Vite dev server)
|
||||
build.ts Vite → codegen → Bun compile 三步构建流水线(含版本号注入)
|
||||
generate-config-schema.ts 配置 JSON Schema 生成与同步校验
|
||||
bump-version-logic.ts 纯版本管理逻辑(parse、validate、bump、format)
|
||||
bump-version.ts 版本升迁 CLI 脚本
|
||||
clean.ts 清理构建产物与临时文件
|
||||
tests/ Bun test 测试(结构镜像 src 目录)
|
||||
@@ -75,13 +77,17 @@ tests/ Bun test 测试(结构镜像 src 目录)
|
||||
server/ 后端测试
|
||||
bootstrap.test.ts
|
||||
config.test.ts
|
||||
config/ 配置模块测试
|
||||
variables.test.ts
|
||||
schema.test.ts
|
||||
middleware.test.ts
|
||||
static.test.ts
|
||||
web/ 前端测试
|
||||
App.test.tsx
|
||||
test-utils.tsx
|
||||
openspec/ OpenSpec 变更、规格文档与 fast-drive workflow schema
|
||||
config.example.yaml 配置文件示例
|
||||
config.example.yaml 配置文件示例(server.listen 布局 + 显式变量引用)
|
||||
config.schema.json 配置文件 JSON Schema(由 bun run schema 生成)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -188,30 +194,74 @@ export function handleMeta(mode: RuntimeMode, version: string): Response;
|
||||
|
||||
### 1.6 配置文件规范
|
||||
|
||||
配置加载流程:
|
||||
配置采用分层生命周期:`unknown → AuthoringConfig → NormalizedConfig → ValidatedConfig → ServerConfig`。
|
||||
|
||||
```
|
||||
CLI argv → parseRuntimeArgs → { configPath? }
|
||||
→ loadServerConfig(configPath)
|
||||
→ 可选 YAML 文件解析 → env 覆盖 → 默认值
|
||||
→ ServerConfig{ host, port }
|
||||
→ 无 configPath → 默认值 { host: "127.0.0.1", port: 3000 }
|
||||
→ 有 configPath → YAML 解析 → normalize(变量替换) → strict validate → resolve → ServerConfig{ host, port }
|
||||
```
|
||||
|
||||
配置加载流程:
|
||||
|
||||
1. **解析 YAML**:`Bun.YAML.parse` 将配置文件解析为 `unknown`
|
||||
2. **normalize**:提取 `variables`,替换 `${KEY}` / `${KEY|default}` 变量引用,移除 `variables` 段,产出 `NormalizedConfig`
|
||||
3. **strict validate**:使用 Ajv + TypeBox 生成的 schema 严格校验(拒绝未知字段、校验类型和范围)
|
||||
4. **resolve**:从校验后的配置中提取 `server.listen.host` 和 `server.listen.port`,填充默认值
|
||||
|
||||
`ServerConfig` 包含以下字段:
|
||||
|
||||
| 字段 | 来源 | 默认值 |
|
||||
| ------ | ------------------------------------------------- | ----------- |
|
||||
| `host` | `process.env["HOST"]` → YAML `server.host` → 默认 | `127.0.0.1` |
|
||||
| `port` | `process.env["PORT"]` → YAML `server.port` → 默认 | `3000` |
|
||||
| 字段 | 来源 | 默认值 |
|
||||
| ------ | ------------------------------------------ | ----------- |
|
||||
| `host` | `server.listen.host`(可含变量引用)→ 默认 | `127.0.0.1` |
|
||||
| `port` | `server.listen.port`(可含变量引用)→ 默认 | `3000` |
|
||||
|
||||
配置文件示例(`config.example.yaml`):
|
||||
|
||||
```yaml
|
||||
# yaml-language-server: $schema=./config.schema.json
|
||||
server:
|
||||
host: "127.0.0.1"
|
||||
port: 3000
|
||||
listen:
|
||||
host: "${HOST|127.0.0.1}"
|
||||
port: ${PORT|3000}
|
||||
```
|
||||
|
||||
变量语法:
|
||||
|
||||
| 语法 | 说明 |
|
||||
| --------------- | ------------------------------ |
|
||||
| `${KEY}` | 引用变量,未定义时报错 |
|
||||
| `${KEY\|value}` | 引用变量,未定义时使用默认值 |
|
||||
| `${KEY\|}` | 引用变量,未定义时使用空字符串 |
|
||||
| `$${KEY}` | 转义,输出 `${KEY}` 原文 |
|
||||
|
||||
变量解析优先级:`variables 字段` → `process.env` → `默认值` → `unresolved 报错`
|
||||
|
||||
完整变量引用保留原始类型,部分拼接转为 string。环境变量不会隐式覆盖配置。
|
||||
|
||||
配置模块结构(`src/server/config/`):
|
||||
|
||||
| 文件 | 职责 |
|
||||
| --------------------- | -------------------------------------------------------- |
|
||||
| `types.ts` | AuthoringConfig、NormalizedConfig、ValidatedConfig 类型 |
|
||||
| `issues.ts` | 结构化配置问题、路径渲染、去重、中文格式化 |
|
||||
| `variables.ts` | 变量提取、引用解析、默认值、环境变量查找、类型推断 |
|
||||
| `normalizer.ts` | Authoring → Normalized 转换(变量替换 + 移除 variables) |
|
||||
| `schema/fragments.ts` | TypeBox schema 片段 |
|
||||
| `schema/builder.ts` | Authoring/Normalized schema 构建 |
|
||||
| `schema/validate.ts` | Ajv strict 校验 + 错误映射 |
|
||||
| `schema/export.ts` | JSON Schema 导出(用于生成 config.schema.json) |
|
||||
|
||||
JSON Schema 相关命令:
|
||||
|
||||
```bash
|
||||
bun run schema # 重新生成 config.schema.json
|
||||
bun run schema:check # 校验 config.schema.json 是否同步
|
||||
```
|
||||
|
||||
运行时依赖 `@sinclair/typebox`(JSON Schema 类型构建)和 `ajv`(JSON Schema 校验),用于配置启动时严格契约校验。
|
||||
|
||||
### 1.7 版本管理
|
||||
|
||||
项目使用 `package.json.version` 作为版本号唯一来源,严格 `MAJOR.MINOR.PATCH` 格式。
|
||||
@@ -573,11 +623,9 @@ bun run verify
|
||||
|
||||
### 3.6 环境变量
|
||||
|
||||
| 变量 | 用途 | 默认值 |
|
||||
| --------------------------- | ----------------------------------------------- | ----------- |
|
||||
| `BUN_TARGET`/`BUILD_TARGET` | 交叉编译目标平台(仅在 `bun run build` 时有效) | 当前平台 |
|
||||
| `HOST` | 服务监听地址 | `127.0.0.1` |
|
||||
| `PORT` | 服务监听端口 | `3000` |
|
||||
| 变量 | 用途 | 默认值 |
|
||||
| --------------------------- | ----------------------------------------------- | -------- |
|
||||
| `BUN_TARGET`/`BUILD_TARGET` | 交叉编译目标平台(仅在 `bun run build` 时有效) | 当前平台 |
|
||||
|
||||
### 3.7 项目配置文件
|
||||
|
||||
@@ -590,7 +638,8 @@ bun run verify
|
||||
| `.prettierrc.json` | Prettier 格式化规则(`printWidth: 120`) |
|
||||
| `.prettierignore` | Prettier 排除路径 |
|
||||
| `.lintstagedrc.json` | lint-staged 配置(TS/TSX → ESLint,MD/JSON/YAML → Prettier) |
|
||||
| `config.example.yaml` | 配置文件示例 |
|
||||
| `config.example.yaml` | 配置文件示例(server.listen 布局 + 显式变量引用) |
|
||||
| `config.schema.json` | 配置文件 JSON Schema(由 bun run schema 生成) |
|
||||
| `vite.config.ts` | Vite 构建配置(React 插件、代码分割、API proxy) |
|
||||
| `bunfig.toml` | Bun 配置(测试 preload、排除规则) |
|
||||
| `opencode.json` | OpenCode 工具配置 |
|
||||
@@ -624,8 +673,10 @@ bun run verify
|
||||
bun run lint # ESLint 检查(含类型感知规则、导入排序、导入验证、Prettier 格式)
|
||||
bun run format # Prettier 自动格式化
|
||||
bun run typecheck # TypeScript 类型检查
|
||||
bun run schema # 生成 config.schema.json
|
||||
bun run schema:check # 校验 config.schema.json 是否同步
|
||||
bun test # 运行所有测试
|
||||
bun run check # 一键运行 typecheck + lint + test
|
||||
bun run check # 一键运行 schema:check + typecheck + lint + test
|
||||
bun run verify # 完整验证(check + build)
|
||||
```
|
||||
|
||||
@@ -735,4 +786,5 @@ bun run verify # 完整验证(check + 构建)
|
||||
- 当前仅为单页面应用,不涉及用户认证和权限控制
|
||||
- 不支持集群部署,单进程运行
|
||||
- 配置文件仅支持 YAML 格式,不支持热加载
|
||||
- 变量替换范围仅限 `server` 子树
|
||||
- 无国际化和多语言支持
|
||||
|
||||
Reference in New Issue
Block a user