Skip to content

Commit 2e70f09

Browse files
🔧 chore(config): 增强配置管理系统文档和类型定义
- 【文档】为配置管理相关类添加详细的 JSDoc 文档注释 - 【类型】优化配置类型定义和类型推导 - 【重构】改进配置生成器和管理器的代码结构 - 【增强】添加配置验证和错误处理的详细注释 - 【优化】完善配置元数据和工具函数的类型定义
1 parent bd1443f commit 2e70f09

File tree

4 files changed

+302
-74
lines changed

4 files changed

+302
-74
lines changed

src/config/ConfigGenerator.ts

+141-47
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
import * as fs from "fs";
22
import * as path from "path";
33

4+
/**
5+
* Interface defining the structure of a configuration definition
6+
* @interface ConfigDefinition
7+
* @property {string} key - The configuration key
8+
* @property {'string'|'boolean'|'number'} type - The type of the configuration value
9+
* @property {any} [default] - Optional default value
10+
* @property {string} description - Description of the configuration
11+
* @property {(readonly string[]|string[])} [enum] - Optional list of allowed values
12+
* @property {(readonly string[]|string[])} [enumDescriptions] - Optional descriptions for enum values
13+
* @property {boolean} [isSpecial] - Optional flag for special configurations
14+
*/
415
export interface ConfigDefinition {
516
key: string;
617
type: "string" | "boolean" | "number";
@@ -11,13 +22,27 @@ export interface ConfigDefinition {
1122
isSpecial?: boolean;
1223
}
1324

25+
/**
26+
* Class responsible for generating and updating configuration related files
27+
* @class ConfigGenerator
28+
*/
1429
export class ConfigGenerator {
30+
/**
31+
* Constants for configuration file paths
32+
* @private
33+
* @readonly
34+
*/
1535
private static CONFIG_FILES = {
1636
PACKAGE: "package.json",
1737
TYPES: "src/config/types.ts",
1838
SCHEMA: "src/config/config-schema.ts",
1939
};
2040

41+
/**
42+
* Adds a new configuration by updating all necessary files
43+
* @param {ConfigDefinition} config - The configuration to add
44+
* @returns {Promise<void>}
45+
*/
2146
static async addConfig(config: ConfigDefinition) {
2247
await Promise.all([
2348
this.updatePackageJson(config),
@@ -26,10 +51,18 @@ export class ConfigGenerator {
2651
]);
2752
}
2853

54+
/**
55+
* Updates package.json with new configuration
56+
* @private
57+
* @param {ConfigDefinition} config - The configuration to add
58+
* @returns {Promise<void>}
59+
*/
2960
private static async updatePackageJson(config: ConfigDefinition) {
61+
// Read package.json
3062
const packagePath = path.join(process.cwd(), this.CONFIG_FILES.PACKAGE);
3163
const pkg = JSON.parse(fs.readFileSync(packagePath, "utf8"));
3264

65+
// Add new configuration
3366
pkg.contributes.configuration.properties[`dish-ai-commit.${config.key}`] = {
3467
type: config.type,
3568
default: config.default,
@@ -40,33 +73,47 @@ export class ConfigGenerator {
4073
: {}),
4174
};
4275

76+
// Write updated package.json
4377
fs.writeFileSync(packagePath, JSON.stringify(pkg, null, 2));
4478
}
4579

80+
/**
81+
* Updates types.ts with new configuration
82+
* @private
83+
* @param {ConfigDefinition} config - The configuration to add
84+
* @returns {Promise<void>}
85+
*/
4686
private static async updateTypes(config: ConfigDefinition) {
4787
const typesPath = path.join(process.cwd(), this.CONFIG_FILES.TYPES);
4888
let content = fs.readFileSync(typesPath, "utf8");
4989

50-
// 处理嵌套配置
90+
// Generate config key based on nesting level
5191
const configKey = config.key.includes(".")
5292
? `${config.key.split(".")[0]}: { ${config.key.split(".")[1]}: ${
5393
config.type
5494
}; }`
5595
: `${config.key}: ${config.type};`;
5696

97+
// Skip if config already exists
5798
if (content.includes(configKey)) {
58-
return; // 如果配置已存在,直接返回
99+
return;
59100
}
60101

61-
// 添加到 ConfigKeys
102+
// Update content with new config
62103
content = this.addToConfigKeys(content, config);
63-
64-
// 添加到 ExtensionConfiguration
65104
content = this.addToExtensionConfiguration(content, config);
66105

106+
// Write updated content
67107
fs.writeFileSync(typesPath, content);
68108
}
69109

110+
/**
111+
* Adds configuration to ConfigKeys section
112+
* @private
113+
* @param {string} content - Current file content
114+
* @param {ConfigDefinition} config - Configuration to add
115+
* @returns {string} Updated content
116+
*/
70117
private static addToConfigKeys(
71118
content: string,
72119
config: ConfigDefinition
@@ -80,64 +127,111 @@ export class ConfigGenerator {
80127
);
81128
}
82129

130+
/**
131+
* Adds configuration to ExtensionConfiguration interface
132+
* @private
133+
* @param {string} content - Current file content
134+
* @param {ConfigDefinition} config - Configuration to add
135+
* @returns {string} Updated content
136+
*/
83137
private static addToExtensionConfiguration(
84138
content: string,
85139
config: ConfigDefinition
86140
): string {
87141
const parts = config.key.split(".");
88142

89-
// 根据现有的配置结构处理路径
143+
// Handle different nesting levels
90144
if (parts.length > 2) {
91-
// 处理两层以上的嵌套,如 features.diffSimplification.enabled
92-
const [section, category, property] = parts;
93-
const parentPath = `${section}.${category}`;
94-
95-
if (!content.includes(`${section}: {`)) {
96-
// 如果主分类不存在,创建完整的嵌套结构
97-
content = content.replace(
98-
/(export interface ExtensionConfiguration {[\s\S]*?)(})/,
99-
`$1 ${section}: {\n ${category}: {\n ${property}: ${config.type};\n };\n };\n$2`
100-
);
101-
} else if (!content.includes(`${parentPath}: {`)) {
102-
// 如果主分类存在但子分类不存在
103-
content = content.replace(
104-
new RegExp(`(${section}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
105-
`$1 ${category}: {\n ${property}: ${config.type};\n };\n $2`
106-
);
107-
} else {
108-
// 如果主分类和子分类都存在,只添加属性
109-
content = content.replace(
110-
new RegExp(`(${parentPath}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
111-
`$1 ${property}: ${config.type};\n $2`
112-
);
113-
}
145+
// Handle multi-level nesting (>2 levels)
146+
return this.handleMultiLevelNesting(content, parts, config.type);
114147
} else if (parts.length === 2) {
115-
// 处理一层嵌套,如 base.language
116-
const [section, property] = parts;
117-
if (!content.includes(`${section}: {`)) {
118-
content = content.replace(
119-
/(export interface ExtensionConfiguration {[\s\S]*?)(})/,
120-
`$1 ${section}: {\n ${property}: ${config.type};\n };\n$2`
121-
);
122-
} else {
123-
content = content.replace(
124-
new RegExp(`(${section}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
125-
`$1 ${property}: ${config.type};\n $2`
126-
);
127-
}
148+
// Handle single-level nesting
149+
return this.handleSingleLevelNesting(content, parts, config.type);
128150
} else {
129-
// 处理顶层配置
130-
content = content.replace(
151+
// Handle top-level config
152+
return content.replace(
131153
/(export interface ExtensionConfiguration {[\s\S]*?)(})/,
132154
`$1 ${config.key}: ${config.type};\n$2`
133155
);
134156
}
135-
return content;
136157
}
137158

159+
/**
160+
* Handles updating content for multi-level nested configurations
161+
* @private
162+
* @param {string} content - Current file content
163+
* @param {string[]} parts - Configuration key parts
164+
* @param {string} type - Configuration type
165+
* @returns {string} Updated content
166+
*/
167+
private static handleMultiLevelNesting(
168+
content: string,
169+
parts: string[],
170+
type: string
171+
): string {
172+
const [section, category, property] = parts;
173+
const parentPath = `${section}.${category}`;
174+
175+
// Handle different cases based on existing structure
176+
if (!content.includes(`${section}: {`)) {
177+
// Create complete nested structure if main section doesn't exist
178+
return content.replace(
179+
/(export interface ExtensionConfiguration {[\s\S]*?)(})/,
180+
`$1 ${section}: {\n ${category}: {\n ${property}: ${type};\n };\n };\n$2`
181+
);
182+
} else if (!content.includes(`${parentPath}: {`)) {
183+
// Add category if main section exists but category doesn't
184+
return content.replace(
185+
new RegExp(`(${section}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
186+
`$1 ${category}: {\n ${property}: ${type};\n };\n $2`
187+
);
188+
} else {
189+
// Add property if both section and category exist
190+
return content.replace(
191+
new RegExp(`(${parentPath}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
192+
`$1 ${property}: ${type};\n $2`
193+
);
194+
}
195+
}
196+
197+
/**
198+
* Handles updating content for single-level nested configurations
199+
* @private
200+
* @param {string} content - Current file content
201+
* @param {string[]} parts - Configuration key parts
202+
* @param {string} type - Configuration type
203+
* @returns {string} Updated content
204+
*/
205+
private static handleSingleLevelNesting(
206+
content: string,
207+
parts: string[],
208+
type: string
209+
): string {
210+
const [section, property] = parts;
211+
212+
if (!content.includes(`${section}: {`)) {
213+
// Create new section if it doesn't exist
214+
return content.replace(
215+
/(export interface ExtensionConfiguration {[\s\S]*?)(})/,
216+
`$1 ${section}: {\n ${property}: ${type};\n };\n$2`
217+
);
218+
} else {
219+
// Add property to existing section
220+
return content.replace(
221+
new RegExp(`(${section}: {[\\s\\S]*?)(}[\n\r\s]*};)`),
222+
`$1 ${property}: ${type};\n $2`
223+
);
224+
}
225+
}
226+
227+
/**
228+
* Updates schema file with new configuration
229+
* @private
230+
* @param {ConfigDefinition} config - The configuration to add
231+
* @returns {Promise<void>}
232+
*/
138233
private static async updateSchema(config: ConfigDefinition) {
139-
// 如果需要更新schema文件的话
234+
// TODO: Implement schema update logic if needed
140235
const schemaPath = path.join(process.cwd(), this.CONFIG_FILES.SCHEMA);
141-
// 根据需要实现schema更新逻辑
142236
}
143237
}

0 commit comments

Comments
 (0)