LiTwin 任务004:JSON Schema、OpenAPI、TypeScript、Java DTO 质量门禁实现

0 阅读5分钟

适用范围

本文对应 LiTwin 工业级轻量化无代码数字孪生引擎的任务 004:契约校验与代码质量流水线。

项目定位来自 README.md:LiTwin 面向工艺工程师,覆盖浏览器端拖拽搭建、Web 轻量化渲染、工业协议双向通信、插件式降阶仿真接入和私有化容器部署,不是纯可视化大屏工具。

当前研发依据为:

docs/12-优化后需求与架构基线.md        唯一需求与架构基线
docs/13-详细架构设计补充.md            模块边界、数据链路、控制状态、运维与测试
docs/14-MVP开发顺序与协作计划.md       12 个月开发顺序、阶段门和协作机制
contracts/openapi.yaml                 REST API v1 契约
contracts/*.schema.json                场景、遥测、插件、控制契约

任务 004 只建立契约和质量门禁,不新增业务 API,不修改数据库业务语义,不扩大三维编辑器、生产 PLC 控制和发布运行时范围。

1. 问题背景

LiTwin 的 contracts/ 是单一契约来源:

scene.schema.json
telemetry.schema.json
plugin-manifest.schema.json
command.schema.json
openapi.yaml

在任务 004 之前,项目已有契约约定,但前端 TypeScript 类型、Java DTO、OpenAPI、后端运行时 schema 副本之间仍主要依赖人工同步。

风险点包括:

风险后果
JSON Schema 修改后运行时副本未同步后端使用旧规则校验场景
OpenAPI 字段改动后 DTO 未跟进接口文档与真实 JSON 不一致
TypeScript interface 漏字段编辑器能编译,但提交内容与契约漂移
Java enum 同名污染校验了错误枚举来源
required 字段没有不可空表达运行时可能出现 null 数据
P3C 只做增量或扫描 0 文件CI 误报质量通过

因此 004 的核心目标是建立统一入口,让这些漂移在本地和 CI 中都能失败。

2. 命令入口

统一入口位于:

scripts/quality.sh

细粒度命令:

命令作用
./scripts/quality.sh validate-contracts校验 JSON Schema、OpenAPI、本地 $ref、关键约束,并触发类型对齐
./scripts/quality.sh check-schema-sync校验运行时 scene.schema.json 副本与 contracts/scene.schema.json 一致
./scripts/quality.sh frontend-typecheck调用前端 TypeScript typecheck
./scripts/quality.sh backend-compileJava 17 后端编译
./scripts/quality.sh backend-unit-test纯 JUnit 单元测试,不依赖 Docker
./scripts/quality.sh p3c-check全量 Java 质量基线扫描
./scripts/quality.sh diff-checkgit diff --check 加未跟踪文本尾随空白检查
./scripts/quality.sh backend-it可选 Testcontainers 集成测试,Docker 不可用时明确报告

组合命令:

./scripts/quality.sh contracts
./scripts/quality.sh frontend
./scripts/quality.sh backend
./scripts/quality.sh all

未知命令和无参数会返回非零,避免 CI 误把帮助输出当成通过。

3. 契约校验

契约校验脚本:

scripts/validate-contracts.js

覆盖内容:

检查项说明
JSON 语法校验 4 个 JSON Schema 可解析
Schema 根结构检查 2020-12 根类型、必填字段、枚举、版本字段
$ref检查 JSON Schema 与 OpenAPI 本地引用可解析,禁止断裂引用
OpenAPI 3.1校验 YAML 可解析、基础结构存在
场景内容引用SceneResource.contentSceneSaveRequest.content 必须直接引用 scene.schema.json
运行时副本backend/api-service/src/main/resources/schemas/scene.schema.jsoncontracts/scene.schema.json 逐字节一致

边界:当前是结构级门禁,不是完整 OpenAPI 3.1 / JSON Schema 语义验证器。后续如接入 Spectral、openapi-tools 或完整 codegen,需要单独升级。

4. TypeScript 与 Java 对齐

对齐脚本:

scripts/check-alignment.js

TypeScript 侧重点:

类型覆盖
interface字段集合、required/optional、基础类型、数组、对象、tuple、$ref
enum/type alias字面量集合与契约枚举一致
oneOfMappingTriggerEventAction 按 type 判别分支递归校验
根结构SceneProject 根字段、schemaVersionprojectscene 完整检查

Java 侧重点:

类型覆盖
DTO 字段按 JSON 序列化名比较字段集合
类型映射string -> Stringinteger -> Integer/Longnumber -> Double/BigDecimaldate-time -> Instantobject -> JsonNode
required 策略primitive 表达数值/布尔不可空;非 primitive required 必须带 @NotNull
optional 策略optional 字段保持可空引用,不允许误加 @NotNull
@JsonProperty真实解析注解,例如 defaultValue 必须映射为 JSON 字段 default
enum 来源使用全限定名校验 Java enum,避免同名枚举覆盖

任务过程中曾发现过真实漂移:前端 AssetRef 缺少契约里的 stats 字段,后续已补齐并纳入门禁。

5. P3C / Java 质量基线

Java 质量脚本:

scripts/check-p3c.js

当前策略是全量扫描:

backend/api-service/src/main/java/**/*.java

任务记录中当前基线为 29 个 Java 文件通过。扫描不到任何 Java 文件时返回非零,避免 CI 干净 checkout 中空跑。

已覆盖的最低规则集:

类别覆盖
命名类型、方法、字段、常量命名
异常空 catch、printStackTrace
日志字符串拼接、敏感信息
线程裸线程池
资源文件流、JDBC connection、statement 需要可靠关闭
代码风格魔法值、通配符 import、控制台输出

边界:参数、局部变量、包名等完整命名规则建议后续统一接入 Checkstyle 或 Alibaba P3C 插件;当前脚本覆盖任务 004 的最低阻断规则。

6. 脚本级自测

自测入口:

node scripts/tests/quality-self-test.mjs

自测不是只跑正向样例,而是固化负例矩阵。典型负例包括:

负例预期
TS 字段类型改错check-alignment 返回非零
oneOf 分支字段改错check-alignment 返回非零
Java DTO 删除字段check-alignment 返回非零
删除 @JsonProperty("default")check-alignment 返回非零
删除 required 字段的 @NotNullcheck-alignment 返回非零
运行时 schema 副本篡改check-schema-sync 返回非零
P3C 加入非法命名、资源泄漏p3c-check 返回非零

任务最终记录为:

node scripts/tests/quality-self-test.mjs   PASS(42/42)

7. 验收记录

任务 004 文件记录的最终验收结果:

node scripts/tests/quality-self-test.mjs   PASS(42/42)
./scripts/quality.sh validate-contracts   PASS
./scripts/quality.sh check-schema-sync    PASS
./scripts/quality.sh p3c-check            PASS(29 个 Java 文件)
./scripts/quality.sh diff-check           PASS
tsc -p frontend/packages/scene-schema/tsconfig.json --noEmit  PASS
Java 17 + Maven 3.6.3 package/unit test   PASS

说明:本文按任务交接与架构验收记录整理,未在写稿过程中重新执行全部命令;因此不使用“实测证明”表述。

8. 使用 AI 大模型开发时的约束

LiTwin 仍然使用 AI 大模型辅助实现,但 004 明确把开发方式压回工程约束:

  1. 先读 README.md 确认项目定位;
  2. docs/12 为唯一需求与架构基线;
  3. docs/13docs/14 约束模块边界、数据链路和开发顺序;
  4. contracts/openapi.yaml 和 JSON Schema 作为接口与数据源头;
  5. 让脚本、自测、负例和架构审核决定是否通过。

模型可以写实现,但不能替代契约、测试和审核。

9. 后续方向

任务 004 完成后,后续资产、实时数据、控制、仿真和发布任务都可以复用同一质量入口。

后续可以继续增强:

  • 接入完整 OpenAPI / JSON Schema 语义校验器;
  • 评审完整 codegen,减少手写 TS/Java 类型;
  • 接入 Checkstyle / Alibaba P3C 插件;
  • 将质量门禁作为 CI 必跑阶段;
  • 为每个业务任务补充对应的负例矩阵。

这次的重点不是“又完成一个功能”,而是让项目后面继续新增功能时,字段、类型和代码质量不再靠人工记忆兜底。