wangzhibo
2026-07-16 b57020623cf0c946706573bf102e548c3a544423
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import { firstUpperCase } from "../utils";
 
/**
 * 将模板字符串扁平化处理,转换为 Service 类型定义
 * @param template - 包含 Service 类型定义的模板字符串
 * @returns 处理后的 Service 类型定义字符串
 * @throws {Error} 当模板中找不到 Service 类型定义时抛出错误
 */
export function flatten(template: string): string {
    // 查找 Service 类型定义的起始位置
    const startIndex = template.indexOf("export type Service = {");
 
    // 保留 Service 类型定义前的内容
    let header = template.substring(0, startIndex);
 
    // 获取 Service 类型定义及其内容,去除换行和制表符
    const serviceTemplateContent = template.substring(startIndex).replace(/\n|\t/g, "");
 
    // 找到 Service 的内容部分
    const serviceStartIndex = serviceTemplateContent.indexOf("{") + 1;
    const serviceEndIndex = findClosingBrace(serviceTemplateContent, serviceStartIndex);
    const serviceInnerContent = serviceTemplateContent
        .substring(serviceStartIndex, serviceEndIndex)
        .trim();
 
    // 存储所有接口定义
    const allInterfaces = new Map<string, string>();
 
    // 处理 Service 内容,保持原有结构但替换嵌套对象为接口引用
    const serviceContent = buildCurrentLevelContent(serviceInnerContent);
 
    // 递归收集所有需要生成的接口
    flattenContent(serviceInnerContent, allInterfaces, []);
 
    // 生成所有接口定义
    let interfaces = "";
    allInterfaces.forEach((content, key) => {
        interfaces += `\nexport interface ${firstUpperCase(key)}Interface { ${content} }\n`;
    });
 
    return `${header}${interfaces}\nexport type Service = { ${serviceContent} }`;
}
 
/**
 * 查找匹配的右花括号位置
 * @param str - 要搜索的字符串
 * @param startIndex - 开始搜索的位置
 * @returns 匹配的右花括号位置
 * @throws {Error} 当找不到匹配的右花括号时抛出错误
 */
function findClosingBrace(str: string, startIndex: number): number {
    let braceCount = 1;
    let currentIndex = startIndex;
 
    while (currentIndex < str.length && braceCount > 0) {
        if (str[currentIndex] === "{") braceCount++;
        if (str[currentIndex] === "}") braceCount--;
        currentIndex++;
    }
 
    if (braceCount !== 0) {
        throw new Error("Unmatched braces in the template");
    }
 
    return currentIndex - 1;
}
 
/**
 * 递归收集所有需要生成的接口
 * @param content - 要处理的内容
 * @param allInterfaces - 存储所有接口定义的 Map
 * @param parentFields - 父级字段数组(暂未使用)
 */
function flattenContent(
    content: string,
    allInterfaces: Map<string, string>,
    parentFields: string[],
): void {
    const interfacePattern = /(\w+)\s*:\s*\{/g;
    let match: RegExpExecArray | null;
 
    while ((match = interfacePattern.exec(content)) !== null) {
        const key = match[1];
        const startIndex = match.index + match[0].length;
        const endIndex = findClosingBrace(content, startIndex);
 
        if (endIndex > startIndex) {
            const innerContent = content.substring(startIndex, endIndex).trim();
 
            // 构建当前接口的内容,将嵌套对象替换为接口引用
            const currentLevelContent = buildCurrentLevelContent(innerContent);
            allInterfaces.set(key, currentLevelContent);
 
            // 递归处理嵌套内容
            flattenContent(innerContent, allInterfaces, []);
        }
    }
}
 
/**
 * 构建当前级别的内容,将嵌套对象替换为接口引用
 * @param content - 内容字符串
 * @returns 处理后的内容
 */
function buildCurrentLevelContent(content: string): string {
    const interfacePattern = /(\w+)\s*:\s*\{/g;
    let result = content;
    let match: RegExpExecArray | null;
 
    // 重置正则表达式的 lastIndex
    interfacePattern.lastIndex = 0;
 
    while ((match = interfacePattern.exec(content)) !== null) {
        const key = match[1];
        const startIndex = match.index + match[0].length;
        const endIndex = findClosingBrace(content, startIndex);
 
        if (endIndex > startIndex) {
            const fullMatch = content.substring(match.index, endIndex + 1);
            const replacement = `${key}: ${firstUpperCase(key)}Interface;`;
            result = result.replace(fullMatch, replacement);
        }
    }
 
    // 清理多余的分号和空格
    result = result.replace(/;+/g, ";").replace(/\s+/g, " ").trim();
 
    return result;
}