From dca304afeb46039f5126682cd665fe55aa5df8ea Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Fri, 10 Apr 2026 20:09:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(config):=20=E6=B7=BB=E5=8A=A0=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=AA=8C=E8=AF=81=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现配置架构解析器,支持对象、数组和标量类型的递归验证 - 添加YAML文档解析功能,包括注释提取和路径映射 - 集成配置验证诊断系统,支持多种数据类型约束检查 - 实现批量编辑器的可编辑字段收集功能 - 添加表单更新应用逻辑,支持标量和数组值的安全更新 - 集成数值约束验证,包括最小值、最大值和倍数检查 - 实现字符串长度和正则表达式模式验证 - 添加枚举值匹配和唯一性约束检查 - 实现配置架构注释提取和样本YAML生成功能 - 支持配置架构默认值和常量值处理 --- .../src/configValidation.js | 5 + .../test/configValidation.test.js | 94 +++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/tools/gframework-config-tool/src/configValidation.js b/tools/gframework-config-tool/src/configValidation.js index 8dcb5de6..59c1f3cb 100644 --- a/tools/gframework-config-tool/src/configValidation.js +++ b/tools/gframework-config-tool/src/configValidation.js @@ -897,6 +897,11 @@ function parseSchemaNode(rawNode, displayPath) { const containsNode = value.contains && typeof value.contains === "object" ? parseSchemaNode(value.contains, joinArrayTemplatePath(displayPath)) : undefined; + if (!containsNode && + (typeof metadata.minContains === "number" || typeof metadata.maxContains === "number")) { + throw new Error(`Schema property '${displayPath}' declares 'minContains' or 'maxContains' without 'contains'.`); + } + if (containsNode && containsNode.type === "array") { throw new Error(`Schema property '${displayPath}' uses unsupported nested array 'contains' schemas.`); } diff --git a/tools/gframework-config-tool/test/configValidation.test.js b/tools/gframework-config-tool/test/configValidation.test.js index 3d3ba6e4..881da545 100644 --- a/tools/gframework-config-tool/test/configValidation.test.js +++ b/tools/gframework-config-tool/test/configValidation.test.js @@ -863,6 +863,64 @@ dropRates: assert.match(diagnostics[0].message, /at most 1 items matching the 'contains' schema|最多只能包含 1 个匹配 contains 条件的元素/u); }); +test("validateParsedConfig should accept satisfied contains constraints", () => { + const schemaWithRange = parseSchemaContent(` + { + "type": "object", + "properties": { + "dropRates": { + "type": "array", + "minContains": 2, + "maxContains": 3, + "contains": { + "type": "integer", + "const": 5 + }, + "items": { + "type": "integer" + } + } + } + } + `); + const yamlWithinRange = parseTopLevelYaml(` +dropRates: + - 0 + - 5 + - 5 + - 10 +`); + + assert.deepEqual(validateParsedConfig(schemaWithRange, yamlWithinRange), []); + + const schemaWithDefaultMinContains = parseSchemaContent(` + { + "type": "object", + "properties": { + "dropRates": { + "type": "array", + "contains": { + "type": "integer", + "const": 5 + }, + "items": { + "type": "integer" + } + } + } + } + `); + const yamlSatisfyingDefaultMinContains = parseTopLevelYaml(` +dropRates: + - 1 + - 2 + - 5 + - 3 +`); + + assert.deepEqual(validateParsedConfig(schemaWithDefaultMinContains, yamlSatisfyingDefaultMinContains), []); +}); + test("validateParsedConfig should accept large decimal multiples without floating-point drift", () => { const schema = parseSchemaContent(` { @@ -1180,6 +1238,42 @@ test("parseSchemaContent should reject nested-array contains schemas", () => { /unsupported nested array 'contains' schemas/u); }); +test("parseSchemaContent should reject minContains and maxContains without contains", () => { + assert.throws( + () => parseSchemaContent(` + { + "type": "object", + "properties": { + "dropRates": { + "type": "array", + "minContains": 1, + "items": { + "type": "integer" + } + } + } + } + `), + /'minContains' or 'maxContains' without 'contains'/u); + + assert.throws( + () => parseSchemaContent(` + { + "type": "object", + "properties": { + "dropRates": { + "type": "array", + "maxContains": 1, + "items": { + "type": "integer" + } + } + } + } + `), + /'minContains' or 'maxContains' without 'contains'/u); +}); + test("parseSchemaContent should reject contains schemas where default minContains exceeds maxContains", () => { assert.throws( () => parseSchemaContent(`